/********************* 问题: 给定一个有向图G=(V,E)和源点s,求s到G中其它每个顶点的最短路径。 Dijkstra算法的具体实现方法: (1)设置两个顶点的集合S和T S中存放已经找到到源点s最短路径的顶点,初始时集合S中只有一个 顶点,即源点s。 T中存放当前还没有找到最短路径的顶点,即T=V-S。 (2)在集合T中选取当前长度最短的一条路径(s,...,v),将v加入到 集合S中,并修改源点s到集合T中每个顶点的最短路径长度;重复这一 步骤,直到所有的顶点都加入到集合S中(即S=V,T=空),算法就结束了。 Dijkstra算法的邻接矩阵实现,复杂度为O(V2)。 *********************/ #include<iostream> //#include<climits> //#include<string> //#include<cstdlib> #include<cstring> #include<cstdio> using namespace std; const int N=5; //最大顶点个数 const int M=10; //最大边数 const int inf=60000; //表示无穷大 int a[N+1][N+1]; //邻接矩阵 int d[N+1]; //记录源点s到顶点u的距离 int pre[N+1]; //记录源点s到顶点u的最短路径上u的前驱 bool vis[N+1]; //表示顶点u是否已经加入集合S中了 void dijkstra(int s){ //求源点s到其它顶点的最短路径 //初始化 for(int i=1; i<=N; ++i){ d[i] = inf; //把d[i]初始化为无穷大 pre[i] = -1; //每个顶点的父节点初始化为空 } d[s] = 0;//s为源点 memset(vis, false, sizeof(vis)); //所有点都不在集合S中 //循环N次,以便于把每个点都加入集合S中 for(int i=1; i<=N; ++i){ int tmp = inf; int k = 0; //找出d值最小的点k for(int j=1; j<=N; ++j){ if(!vis[j] && d[j]<tmp){ tmp = d[j]; k = j; } } if(k==0) return; //没有点可以加入集合S中了,剩余点不可达 vis[k] = true; //把点k加入集合S //更新k的邻居(不在集合S的)的d值 for(int j=1; j<=N; ++j){ if(!vis[j] && d[j]>d[k]+a[k][j]){ d[j] = d[k]+a[k][j]; pre[j] = k; } } } } void print_path(int s, int v){ if(v==s){ printf("%d", s); } else{ if(pre[v] == -1) printf("path no exist! "); else{ print_path(s, pre[v]); printf("->%d", v); } } } int main() { freopen("shortpath.in", "r", stdin); int u, v, w; //边(u, v)和权值w for( int i=1; i<=N; ++i) //初始化邻接矩阵 for( int j=1; j<=N; ++j){ if(i==j) a[i][j] = 0; else a[i][j] = inf; } for(int i=1; i<=M; ++i){ cin>>u>>v>>w; a[u][v] = w; a[v][u] = w; } int s=1; //选择的一个源点 dijkstra(s); //求源点s到其它顶点的最短路径 for(int v=1; v<=N; ++v){ if(v==s) continue; printf("%d ", d[v] ); //打印s到顶点v的最短路径长度 print_path(s, v); //打印出源点s到v的路径 printf(" "); } return 0; }