点击进入例题 最短路
我知道的有三种方法 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
",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
",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
",d[n]);
59 }
60 }