完善刘佳汝紫书P361、P362的代码
邻接矩阵存稀疏图太耗内存了 这种写法感觉不错 copy一下
写的有点急 可能有的地方有错误 有些地方还可以在优化 p数组记录路径未验证 以后还会在写一个用 pair 的迪杰斯特拉写法
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <iostream> 6 #include <sstream> 7 #include <algorithm> 8 #include <string> 9 #include <queue> 10 #include <vector> 11 using namespace std; 12 const int maxn= 1e5+10; 13 const int maxm= 1e4+10; 14 const int inf = 1008611; 15 typedef long long ll; 16 int n,m,s; //n个点1~n m 条边 起点 s 17 int d[maxn],done[maxn],p[maxn]; //d[i]表示i点到起点s的最短路距离 18 //done[u]==1表示u点到起点点s的最短路已经找到 19 //p[i]表示起点s到i的最短路径与i点相连的上一条边 20 struct edge //边结构体 21 { 22 int from,to,dis; 23 }; 24 vector<edge> edges; //边集 无向图 边数*2 25 vector<int> g[maxn]; //g数组存的是边的序号 26 struct mindis //压入优先队列的结构体 因为d[u]和u要绑定起来 才可标记 u是否已确定最短路 27 { 28 int d,u; 29 bool operator <(const mindis& rhs)const{ 30 return d>rhs.d; //距离最小值优先 距离相等无所谓 随便一个先出 边权是正的 两个会依次访问 不会影想结果 31 } 32 }; 33 void init(int n) //每次输入数据清空容器 34 { 35 for(int i=0;i<=n;i++) 36 g[i].clear(); 37 edges.clear(); 38 } 39 void addedge(int from,int to,int dis) //加边操作 40 { 41 edges.push_back((edge){from,to,dis}); //将边压入边集 42 int k=edges.size(); 43 g[from].push_back(k-1); //k-1为边序号 以后调用边集数组要从下标0开始 所以边的编号从0开始 将边序号压入已from为起点的数组 44 } 45 void dijkstra(int s) //主算法 46 { 47 for(int i=0;i<=n;i++) //把距离初始化为 inf 不能用memset 自己估算一下路径最长有多长 inf定义大一点就好 48 d[i]=inf; 49 d[s]=0; //到自己的最短距离直接设为0 50 priority_queue<mindis> q; //优先队列 小顶堆 最小值优先 51 q.push((mindis){0,s}); 52 memset(done,0,sizeof(done)); //初始化数组 53 memset(p,-1,sizeof(p)); 54 while(!q.empty()) //队列非空 55 { 56 mindis x=q.top(); //取当前最小值 57 q.pop(); 58 int u=x.u; 59 if(done[u]==1) //已确定路径直接跳过 60 continue; 61 done[u]=1; //标记 已确定 62 for(int i=0;i<g[u].size();i++) 63 { 64 edge e =edges[g[u][i]]; //g[u][i]表示以u为起点的第i条边在边集edges中的下标 65 if(d[e.to]>d[u]+e.dis) //满足条件更新距离 66 { 67 d[e.to]=d[u]+e.dis; 68 p[e.to]=g[u][i]; //保存路径 69 q.push((mindis){d[e.to],e.to}); //把更新完的值压入队列 70 } 71 } 72 } 73 } 74 int main() 75 { 76 scanf("%d %d %d",&n,&m,&s); 77 init(n); 78 int u,v,w; 79 for(int i=0;i<m;i++) 80 { 81 scanf("%d %d %d",&u,&v,&w); 82 addedge(u,v,w); 83 addedge(v,u,w); //无向图相互可达 有向图一次就好 84 } 85 dijkstra(s); 86 // for(int i=0;i<edges.size();i++) 87 // { 88 // printf("%d %d %d %d ",i,edges[i].from,edges[i].to,edges[i].dis); 89 // } 90 // for(int i=1;i<=n;i++) 91 // { 92 // printf("%d ",i); 93 // for(int j=0;j<g[i].size();j++) 94 // printf("%d ",g[i][j]); 95 // printf(" "); 96 // } 97 for(int i=1;i<=n;i++) //打印每个点到起点s的最短距离 98 printf("%d ",d[i]); 99 return 0; 100 } 101 //样例 102 //6 9 5 103 //5 4 6 104 //5 1 3 105 //5 2 5 106 //4 1 4 107 //1 2 1 108 //4 3 4 109 //1 3 2 110 //2 3 3 111 //3 6 4
欢迎交流!!~~~