Dijkstra求单源最短路模板

本文详细介绍Dijkstra算法的实现过程,包括使用前向星存储结构、优先队列等数据结构优化算法效率的方法。通过实例讲解如何求解单源最短路径问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 #include <cstdio>

 2 #include <cstring>

 3 #include <algorithm>

 4 #include <iostream>

 5 #include <queue>

 6 #define MAX 9999999

 7 

 8 using namespace std;

 9 //pair 的first 保存的为最短距离, second保存的为顶点编号

10 typedef pair<int, int >P;//对组  不知道请自行百度   

11 

12 struct node

13 {

14     int v, w;//v 为到达的点, w为权重

15     int next;//记录下一个结构体的位置 ,就向链表的next功能是一样的

16 };

17 node edge[2003];//存所有的边,因为是无向图,所以*2

18 int cnt;//结构体的下标

19 int n, s, t;//n 点数,s 起点,t止点

20 int head[203];//和链表的头指针数组是一样的。只不过此处head[u]记录的为最后加入 edge 的且与u相连的边在 edge 中的位置,即下标

21 

22 void add(int u, int v, int w)//加边操作

23 {

24     edge[cnt].v = v;

25     edge[cnt].w = w;

26     edge[cnt].next = head[u];//获得下一个结构体的位置

27     head[u] = cnt++;//记录头指针的下标

28 }

29 

30 void dijkstra()

31 {

32     int dis[203];//最短路径数组

33     int i, v;//v保存从队列中取出的数的第二个数  也就是顶点的编号

34     priority_queue<P,vector<P>,greater<P> >que;//优先队列 从小到大

35     node e;//保存边的信息,为了书写方便

36     P p;//保存从队列取出的数值

37 

38     fill(dis,dis+n,MAX);//初始化,都为无穷大

39     dis[s] = 0;//s—>s  距离为0

40     que.push(P(0,s));//放入距离 0   点为s

41     while(!que.empty()){

42         p = que.top();//取出队列中最短距离最小的对组

43         que.pop();//删除

44         v = p.second;//获得最短距离最小的顶点编号

45         if(dis[v] < p.first)//若取出的不是最短距离

46             continue;//则进行下一次循环

47         for(i=head[v];i!=-1;i=edge[i].next)//对与此点相连的所有的点进行遍历

48         {

49             e = edge[i];//为了书写的方便。

50             if(dis[e.v]>dis[v]+e.w){//进行松弛

51                 dis[e.v]=dis[v]+e.w;//松弛成功

52                 que.push(P(dis[e.v],e.v));//讲找到的松弛成功的距离 和顶点放入队列

53             }

54         }

55     }

56     printf("%d\n",dis[t]==MAX?-1:dis[t]);//输出结果

57 }

58 

59 int main()

60 {

61     int m, u, v, w;

62 

63     while(scanf("%d %d",&n,&m)==2){//获取点数  边数

64         cnt = 0;//结构体下标从0开始

65         memset(head,-1,sizeof(head));//初始化head[N]数组

66         while(m--){

67             scanf("%d %d %d",&u,&v,&w);//获取u,v,w(u,v)

68             add(u,v,w);//加边

69             add(v,u,w);//加边

70         }

71         scanf("%d %d",&s,&t);//获取起止点

72         dijkstra();

73     }

74     return 0;

75 }

题解在此

用到的数据结构 :前向星 对组 优先队列

 1 //pair 的first 保存的为最短距离, second保存的为顶点编号

 2 typedef pair<int, int >P;//对组  不知道请自行百度   

 3 

 4 struct node//前向星存边

 5 {

 6     int v, w;//v 为到达的点, w为权重

 7     int next;//记录下一个结构体的位置 ,就向链表的next功能是一样的

 8 };

 9 node edge[2003];//存所有的边,因为是无向图,所以*2

10 int head[203];//和链表的头指针数组是一样的。只不过此处head[u]记录的为最后加入 edge 的且与u相连的边在 edge 中的位置,即下标

11 

12 priority_queue<P,vector<P>,greater<P> >que;//优先队列 从小到大

在此我们说一下前向星的加边函数

1 void add(int u, int v, int w)//加边操作

2 {

3     edge[cnt].v = v;

4     edge[cnt].w = w;

5     edge[cnt].next = head[u];//获得下一个结构体的位置

6     head[u] = cnt++;//记录头指针的下标

7 }

主函数对数据的获取

 1 int main()

 2 {

 3     int m, u, v, w;

 4 

 5     while(scanf("%d %d",&n,&m)==2){//获取点数  边数

 6         cnt = 0;//结构体下标从0开始

 7         memset(head,-1,sizeof(head));//初始化head[N]数组

 8         while(m--){

 9             scanf("%d %d %d",&u,&v,&w);//获取u,v,w(u,v)

10             add(u,v,w);//加边

11             add(v,u,w);//加边

12         }

13         scanf("%d %d",&s,&t);//获取起止点

14         dijkstra();

15     }

16     return 0;

17 }

Dijkstra算法求值

 1 void dijkstra()

 2 {

 3     int dis[203];//最短路径数组

 4     int i, v;//v保存从队列中取出的数的第二个数  也就是顶点的编号

 5     priority_queue<P,vector<P>,greater<P> >que;//优先队列 从小到大

 6     node e;//保存边的信息,为了书写方便

 7     P p;//保存从队列取出的数值

 8 

 9     fill(dis,dis+n,MAX);//初始化,都为无穷大

10     dis[s] = 0;//s—>s  距离为0

11     que.push(P(0,s));//放入距离 0   点为s

12     while(!que.empty()){

13         p = que.top();//取出队列中最短距离最小的对组

14         que.pop();//删除

15         v = p.second;//获得最短距离最小的顶点编号

16         if(dis[v] < p.first)//若取出的不是最短距离

17             continue;//则进行下一次循环

18         for(i=head[v];i!=-1;i=edge[i].next)//对与此点相连的所有的点进行遍历

19         {

20             e = edge[i];//为了书写的方便。

21             if(dis[e.v]>dis[v]+e.w){//进行松弛

22                 dis[e.v]=dis[v]+e.w;//松弛成功

23                 que.push(P(dis[e.v],e.v));//讲找到的松弛成功的距离 和顶点放入队列

24             }

25         }

26     }

27     printf("%d\n",dis[t]==MAX?-1:dis[t]);//输出结果

28 }

### Dijkstra算法实现短路径计算 Dijkstra算法是一种经典的图论算法,用于解加权有向图中的单源短路径问题。该算法的核心思想是从起始节点出发,逐步扩展已知的短路径集合,直到找到目标节点或遍历整个图为止。 #### 算法的基本原理 Dijkstra算法通过维护一个距离数组 `dist[]` 来记录从起点到各个顶点的当前短路径长度,并利用优先队列来动态更新这些距离值。每次从未访问过的节点中选取具有小距离值的节点作为新的中间节点,以此为基础进一步探索其相邻节点的距离[^2]。 以下是使用Python语言实现的一个简单版本: ```python import heapq def dijkstra(graph, start): n = len(graph) dist = [float('inf')] * n # 初始化距离数组为无穷大 visited = [False] * n # 标记是否已经确定短路径 dist[start] = 0 # 起点到自身的距离为0 heap = [(0, start)] # 小根堆存储 (当前距离, 当前节点) while heap: current_dist, u = heapq.heappop(heap) # 取出未处理的近节点 if visited[u]: continue visited[u] = True for v, weight in graph[u]: # 遍历邻居节点 if not visited[v] and dist[u] + weight < dist[v]: dist[v] = dist[u] + weight # 更新更短的距离 heapq.heappush(heap, (dist[v], v)) # 加入待处理列表 return dist ``` 此代码片段展示了如何构建并运行Dijkstra算法。其中输入参数是一个邻接表形式表示的图 `graph` 和指定的起点索引 `start`。函数返回的是一个包含从起点到达每个节点所需短路径长度的一维数组 `dist[]`[^1]。 对于C++环境下的具体实现方式可以参考如下模板: ```cpp #include <vector> #include <queue> #include <climits> using namespace std; struct Node { int to; long cost; }; long dijkstra(int s, vector<vector<Node>> &G){ const int INF = INT_MAX / 2; // 定义极大值防止溢出 priority_queue<pair<long,int>, vector<pair<long,int>>, greater<>> pq; vector<long> d(G.size(),INF); d[s]=0; pq.emplace(0,s); while(!pq.empty()){ pair<long,int> p=pq.top();pq.pop(); int v=p.second; if(d[v]<p.first)continue; for(auto e : G[v]){ if(d[e.to]>d[v]+e.cost){ d[e.to]=d[v]+e.cost; pq.emplace(d[e.to],e.to); } } } return (*max_element(d.begin()+1,d.end())!=INF)?*max_element(d.begin()+1,d.end()):-1; } ``` 上述两段伪码分别提供了两种主流编程语言下执行迪杰斯特拉方法的具体流程说明及其逻辑框架[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值