首页 > 编程语言 >单源最短路径算法

单源最短路径算法

时间:2023-08-09 22:24:53浏览次数:58  
标签:int 路径 单源 距离 算法 edge 节点 dis

单源最短路径算法

1. 原理

单源最短路径算法是一种用于在有向图或无向图中找到从指定源节点到其他所有节点的最短路径的算法。常用的单源最短路径算法有Dijkstra算法、Floyd-Warshall算法和Bellman-Ford算法。

2. Dijkstra算法

Dijkstra算法是最常用的单源最短路径算法之一,它的基本思想是:从源节点开始,每次选择距离源节点最近的一个未访问过的邻居节点,更新其距离值,直到所有节点都被访问过。

2.1 算法流程

  1. 初始化:将所有节点的距离值设为无穷大,源节点的距离值设为0。创建一个距离数组dist,用于存储每个节点到源节点的距离。同时创建一个访问数组vis,用于标记每个节点是否被访问过。
  2. 选择未访问过的邻居节点中距离最小的节点u。
  3. 将节点u的距离值更新为当前距离值加上u与源节点之间的边权值。
  4. 标记节点u为已访问。
  5. 重复步骤2-4,直到所有节点都被访问过。
  6. 从源节点出发,根据dist数组回溯得到最短路径。

2.2 C++代码实现

#include<bits/stdc++.h>
#define reg register
using namespace std;

// 读取输入的整数,包括正负号和可能的小数部分
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

// 输出整数,包括正负号和小数部分
void write(int x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return ;
}

const int MAXN=100005,MAXM=200005,INF=(1<<30);
struct node_1{
    int to,dis,next;
};
struct node_2{
    int dis,pos;
    bool operator <(const node_2 &x)const{
        return x.dis<dis;
    }
};
priority_queue<node_2 > q; // 优先队列,用于存储待处理的节点,按照距离从小到大排序
vector<node_1 > edge; // 存储图的边的信息,包括目标节点、距离等信息
int head[MAXN],dis[MAXN],cnt,n,m,s; // n为节点数量,m为边的数量,s为起始节点编号
bool vis[MAXN]; // 标记节点是否已经被访问过

// 添加一条边到图中,参数分别为起点、终点和距离
inline void add_edge(int u, int v, int d){
    edge.push_back((node_1){v,d,head[u]}); // 将终点、距离和头结点的信息存入edge向量中
    head[u]=edge.size()-1; // 将头结点的指针指向当前边的尾部结点的位置
    return ;
}

// Dijkstra算法求解最短路径问题,参数为起始节点编号s和邻接矩阵表示的图edge
inline void dijkstra(){
    dis[s]=0; // 将起始节点的距离设为0,并将其加入优先队列中
    q.push((node_2){0,s}); // 将起始节点的信息存入优先队列中,按照距离从小到大排序
    while(!q.empty()){ // 当优先队列不为空时,循环执行以下操作
        node_2 tmp=q.top(); // 取出队首元素,即当前距离最小的节点及其距离值tmp.dis和位置tmp.pos
        q.pop(); // 将该节点从队列中移除
        int x=tmp.pos,d=tmp.dis; // 将该节点的位置和距离值分别赋给变量x和d
        if(vis[x]) continue; // 如果该节点已经被访问过,则跳过本次循环,继续处理下一个节点
        vis[x]=1; // 将该节点标记为已访问过
        for(reg int i=head[x];i;i=edge[i].next){ // 从该节点开始遍历其所有邻居节点,直到链表的尾部结点为止
            int y=edge[i].to,val=dis[x]+edge[i].dis; // 将邻居节点的信息存入变量y和val中
            if(dis[y]>val){ // 如果通过当前节点到达邻居节点的距离小于已知的最短距离值val.dis,则更新最短距离值和对应的节点位置信息
                dis[y]=val; // 将邻居节点的最短距离值设为val.dis
                if(!vis[y]){ // 如果邻居节点还没有被访问过,则将其加入优先队列中,按照距离从小到大排序
                    q.push((node_2){dis[y],y}); // 将邻居节点的最短距离值和位置信息存入优先队列中,按照距离从小到大排序
                }
            }
        }
    }
}

int main(){ // 主函数,程序的入口点
    n=read(),m=read(),s=read(); // 从输入中读取节点数量、边数量和起始节点编号s的值并存入相应的变量中
    edge.push_back((node_1){0,0,0}); 
    for(reg int i=1;i<=n;++i)	dis[i]=INF;
	for(reg int i=0;i<m;++i){
		int u=read(),v=read(),d=read();
		add_edge(u,v,d);
	}
	dijkstra();
	for(reg int i=1;i<=n;++i){
		write(dis[i]);
		putchar(' ');
	}
	return 0;
}

标签:int,路径,单源,距离,算法,edge,节点,dis
From: https://www.cnblogs.com/Nebulary/p/17618135.html

相关文章

  • (未完全掌握)代码随想录算法训练营第八、九天|KMP算法;力扣28.实现strStr(),力扣459.重
    KMP算法(没掌握)主要功能:字符串匹配理论:检测文本串中是否出现过模式串前缀就是包含首字母不包含尾字母的所有子串后缀就是包含尾字母不包含首字母的所有子串最长相等前后缀:对子串分别分析,从左向右前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从......
  • Floyd 算法
    Floyd算法:动态规划中的最短路径问题一、简介Floyd算法是一种用于求解图中所有顶点对之间最短路径的动态规划算法。它是由RobertW.Floyd在1965年提出的,因此得名Floyd-Warshall算法。该算法的核心思想是使用动态规划来避免重复计算已经计算过的子问题的解。二、原理假......
  • 分解因数--递归算法
    【题目描述】给出一个正整数a,要求分解成若干个正整数的乘积,即a=a1×a2×a3×...×an,并且1<a1≤a2≤a3≤...≤an,问这样的分解的种数有多少。注意到a=a也是一种分解。【输入】第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a(1<a<32768)。【输出】n行,每......
  • MATLAB用改进K-Means(K-均值)聚类算法数据挖掘高校学生的期末考试成绩|附代码数据
    全文链接:http://tecdat.cn/?p=30832最近我们被客户要求撰写关于K-Means(K-均值)聚类算法的研究报告,包括一些图形和统计输出。本文首先阐明了聚类算法的基本概念,介绍了几种比较典型的聚类算法,然后重点阐述了K-均值算法的基本思想,对K-均值算法的优缺点做了分析,回顾了对K-均值改进......
  • LeetCode从算法到算命—1749.任意子数组和的绝对值的最大值
    1749.任意子数组和的绝对值的最大值题目信息给你一个整数数组nums。一个子数组[numsl,numsl+1,...,numsr-1,numsr]的和的绝对值为abs(numsl+numsl+1+...+numsr-1+numsr)。请你找出nums中和的绝对值最大的任意子数组(可能为空),并返回该最大值。abs(x)......
  • 1) 最短路径 思路
    一、名词解释临接矩阵:Dijkstra算法:G: graphV: vertexE:edge 二、生成临接矩阵   a->b(1)b->c(5)b->d(2)d->c(2) ......
  • 最短路算法大全(Bellman-Ford &Spfa)
    Bellman-Ford算法1、基于松弛操作的单源最短路算法,针对于有向图、2、e[u]存u点的出边的邻点和边权,d[u]存u点到原点的距离3、初始化,d[s]=0,d[其他点]=INF(源点到本身的距离初始化为0到其他点的距离都初始化为无穷)4、执行多轮操作。每轮操作都对所有边尝试一次松弛操作5、......
  • 非对称加密算法
    非对称加密算法是一种使用公钥和私钥配对的加密算法,也称为公钥加密算法.常见的非对称加密算法包括RSA、DSA等,它们遵循公钥分发、私钥保密规则,也就是说公钥是公开的,可以自由分发给其他人.而私钥是保密的,只有私钥的持有者知道.这样可以确保加密和签名的安全性,因为即使公钥......
  • 堆优化模拟退火(List-Based Simulated Annealing|List-Based SA|LBSA|模拟退火) 算法
    堆优化模拟退火(List-BasedSimulatedAnnealing)算法引入堆优化模拟退火(List-BasedSimulatedAnnealing,简称LBSA)是一种对模拟退火的优化算法。由Shi-huaZhan,[1],[2]JuanLin,[1:1]Ze-junZhang,[1:2]Yi-wenZhong[1:3],[2:1]提出。(以下我们以求最小值为例)解释我们......
  • 文心一言 VS 讯飞星火 VS chatgpt (73)-- 算法导论7.1 4题
    四、如何修改QUICKSORT,使得它能够以非递增序进行排序?文心一言:快速排序(Quicksort)是一种常用的排序算法,基于分治策略进行设计。默认情况下,快速排序会以递增序进行排序。若想修改快速排序以实现非递增排序,我们需要调整比较和交换的逻辑。以下是修改后的非递增快速排序的Python代码......