3最短路的几种解法 ------例题< 最短路 >
点击进入例题 最短路
我知道的有三种方法 1 : 深搜 每次 每次有更小的路径时 就更新 , 2 : Dijkstra 3 : floyd
前两种 是 单源 最短路径 , 如果是 求 单源最短路径的话 就用前面的 两种 , 但是 如果求的是 多源最短路径的话 最好是还用 floyd 时间复杂度 相对较低 . 用floyd 求单源最短路径的话 .... 时间复杂度 搞那么一点点 不过 程序实现简单 ,
1 : floyd 的 实现方法
#include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<set> #include<stack> #include<string> #include<sstream> #include<map> #include<cctype> using namespace std; #define INF 99999999 int main() { int e[101][101]; int n,m,a,b,c,i,j,k; while(~scanf("%d %d",&n,&m)&&n!=0&&m!=0) { for(i=1;i<=n;i++) // 将 各个边 初始化 为 最大值 for(j=1;j<=n;j++) e[i][j]=INF; while(m--) { scanf("%d%d%d",&a,&b,&c); // 确定边 和 边长 e[b][a]=e[a][b]=c; } for(k=1;k<=n;k++) //Floyd核心算法... { for(i=1;i<=n;i++) // 所有的 路 都让 k 加进去试试 { for(j=1;j<=n;j++) //如果 从 i到j的路上 有k 走的会更轻松的话 , 那就让 k 去吧 { if(e[i][j]>e[i][k]+e[k][j]) // 判断 是否会 更加轻松 e[i][j]=e[i][k]+e[k][j]; } } } printf("%d\n",e[1][n]); } }
2 : 深搜完成 . ( 超时 ..... 数据处理应该是没有问题的 )
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #include<set> 9 #include<stack> 10 #include<string> 11 #include<sstream> 12 #include<map> 13 #include<cctype> 14 using namespace std; 15 #define INF 99999999 16 int n,m,a[105][105],result; 17 vector<int>v[105]; 18 void DFS(int star,int dis) 19 { 20 if(dis>=result) 21 return; 22 if(star==n) 23 { 24 result=result>dis?dis:result; 25 return ; 26 } 27 for(int i=0;i<v[star].size();i++) 28 { 29 if(a[star][v[star][i]]!=INF) 30 { 31 int w=a[star][v[star][i]]; 32 a[star][v[star][i]]=INF; 33 a[v[star][i]][star]=INF; 34 DFS(v[star][i],w+dis); 35 a[star][v[star][i]]=w; 36 a[v[star][i]][star]=w; 37 } 38 } 39 } 40 int main() 41 { 42 for(int i=0;i<105;i++) 43 for(int j=0;j<105;j++) 44 a[i][j]=INF; 45 while(scanf("%d%d",&n,&m),(m||m)) 46 { 47 result=INF; 48 for(int i=0;i<m;i++) 49 { 50 int d,b,c; 51 scanf("%d%d%d",&d,&b,&c); 52 v[d].push_back(b); 53 v[b].push_back(d); 54 a[d][b]=c; 55 a[b][d]=c; 56 } 57 DFS(1,0); // 从 1 到 n . 58 printf("%d\n",result); 59 } 60 }
3 : Dijkstra ( 也就这一个比较有意思一点 ) < 归根结底 所有的算法 都是 模拟 ... >
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 using namespace std; 5 #define N 0x1f1f1f1f 6 int w[151][151]; 7 int d[155]; 8 int ans,vis[151]; 9 int n,m; 10 void Dij() // Dijkstra 11 { 12 int i,j,k,v,tmp; 13 memset(vis,0,sizeof(vis)); 14 for(i=1;i<=n;i++) // 图 中 每个节点 和 1 的距离 不是直接相邻的 就是 正无穷 15 d[i]=w[1][i]; 16 d[1]=0; 17 vis[1]=1; 18 for(i=1;i<=n;i++) 19 { 20 tmp=N; 21 for(j=1;j<=n;j++) 22 { 23 if(tmp>d[j]&&!vis[j]) // 从中 找到一个 和 1 最近的点 ( 这就是 怪姥姥讲的 已经有的 确定集合了吧 ) 24 { 25 tmp=d[j]; 26 v=j; // 记录下来 那一个端点的 标号 27 } 28 } 29 vis[v]=1; // 最短的 端点 假如集合 , 标记为 已经在 集合以内 30 for(k=1;k<=n;k++) 31 { 32 if(!vis[k]) // 将所有 集合之外 但是 和 集合之中 最少一个元素相连的元素 的长度 算一下 33 d[k]=min(d[k],d[v]+w[v][k]); // 但是 不让他们加进去 一会 在上面 检查一个最小的 假如已经确定长度的 集合之中 34 } 35 } 36 } 37 int main() 38 { 39 printf("%d",N); 40 while(~scanf("%d%d",&n,&m)) 41 { 42 if(n==0&&m==0)break; 43 for(int i=1;i<=n;i++) 44 { 45 for(int j=1;j<=n;j++) 46 { 47 w[i][j]=0x1f1f1f1f; 48 } 49 } 50 for(int i=0;i<m;i++) 51 { 52 int a,b,dis; 53 scanf("%d%d%d",&a,&b,&dis); 54 if(w[a][b]>dis) 55 w[a][b]=w[b][a]=dis; 56 } 57 Dij(); 58 printf("%d\n",d[n]); 59 } 60 }