1 最短路
2 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
3 Total Submission(s): 98085 Accepted Submission(s): 42348
4
5
6 Problem Description
7 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
8
9
10
11 Input
12 输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
13 输入保证至少存在1条商店到赛场的路线。
14
15
16 Output
17 对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
18
19
20 Sample Input
21 2 1
22 1 2 3
23 3 3
24 1 2 5
25 2 3 5
26 3 1 2
27 0 0
28
29
30 Sample Output
31 3
32 2
33
34
35 Source
dijkstra算法不能解决负边权的问题
floyed算法可以解决负边权问题 但是算法效率比较低效
spfa算法也可以解决负边权问题 效率也比folyed算法要高得多
无向图 可以采用dijkstra算法
1 //dijk 算法 (单源)
2
3 #include <iostream>
4 #include <cstdio>
5 #include <cstdlib>
6 #include <cstring>
7 #include <iostream>
8 #include <algorithm>
9 #include <cmath>
10 #include <queue>
11 #include <set>
12 #include <map>
13 using namespace std;
14 #define pi acos(-1.0)
15 #define ll long long
16 int n,m;
17 int a,b,c;
18 const int N =150;
19 int g[N][N],d[N];
20 const int inf = 0x3f3f3f3f;
21 bool vis[N];
22 void init()
23 {
24 for(int i=0;i<N;i++){
25 for(int j=0;j<N;j++){
26 if(i==j) g[i][j]=0;
27 else g[i][j]=inf;
28 }
29 d[i]=inf;
30 }
31 memset(vis,0,sizeof(vis));
32 }
33 void dijk(int s,int e,int n){
34 d[s]=0;
35 for(int i=0;i<n-1;i++){//每次找出一个s到一个点的最短距离,因此至少n-1次循环
36 int minn,min_num;
37 minn=inf;
38 for(int j=1;j<=n;j++){
39 if(minn>d[j]&&!vis[j]){
40 minn=d[j];
41 min_num=j;
42 }
43 }
44 vis[min_num]=1;
45 for(int k=1;k<=n;k++){
46 if(!vis[k]&&d[k]>d[min_num]+g[min_num][k]){
47 d[k]=d[min_num]+g[min_num][k];
48 }
49 }
50 }
51 }
52 int main()
53 {
54 while(~scanf("%d%d",&n,&m)){
55 if(n==0&&m==0) break;
56 init();
57 for(int i=0;i<m;i++){
58 scanf("%d%d%d",&a,&b,&c);
59 g[a][b]=g[b][a]=c;
60 }
61 dijk(1,n,n);
62 printf("%d
",d[n]);
63 }
64 return 0;
65 }
//flord 算法(多源)
//https://blog.csdn.net/amazingcode/article/details/53038977 挺好的
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define pi acos(-1.0)
#define ll long long
int n,m;
int a,b,c;
const int N =150;
int f[N][N];
const int inf = 0x3f3f3f3f;
void init()
{
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(i==j) f[i][j]= 0;
else{
f[i][j] = inf;
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
init();
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
f[a][b]=f[b][a]=c;
}
for(int k=1;k<=n;k++){//k 在最外层
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
}
}
printf("%d
",f[1][n]);
}
return 0;
}
1 /*
2 算法原理
3 这个算法因为与贝尔曼福德(Bellman-Ford)算法比较相似,只是在它的算法的基础上进行了队列优化,因此也被嘲讽为“队列优化的贝尔曼福德”。
4
5 就是每次可以更新到一个节点的最短距离的时候,我们就更新它,并更新所有它能到达的子节点,直到没有节点需要被更新。
6
7 */
8 //spfa 单源
9 #include <iostream>
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #include <cmath>
16 #include <queue>
17 #include <set>
18 #include <map>
19 using namespace std;
20 #define pi acos(-1.0)
21 #define ll long long
22 int n,m;
23 int a,b,c;
24 const int N =150;
25 int d[N],f[N][N];
26 const int inf =0x3f3f3f3f;
27 bool vis[N];
28 void init()
29 {
30 for(int i =0;i<N;i++){
31 for(int j=0;j<N;j++){
32 f[i][j]=(i==j)?0:inf;
33 }
34 d[i] = inf ;
35 vis[i] = 0;
36 }
37
38 }
39 void spfa(int st)
40 {
41 d[st] = 0;
42 queue<int>Q;
43 while(!Q.empty()) Q.pop();
44 Q.push(st);
45 vis[st] =1;
46 while(!Q.empty()){
47 int u =Q.front();
48 Q.pop();
49 vis[u] =0;
50 for(int i =1;i<=n;i++){
51 if(d[i]>d[u]+f[u][i]){
52 d[i] = d[u] +f[u][i];
53 if(!vis[i]){
54 vis[i] = 1;
55 Q.push(i);
56 }
57 }
58 }
59 }
60 }
61 int main()
62 {
63 while(~scanf("%d%d",&n,&m)&&(n+m)){
64 init();
65 for(int i=0;i<m;i++){
66 scanf("%d%d%d",&a,&b,&c);
67 f[a][b] = f[b][a] = c;
68 }
69 spfa(1);
70 printf("%d
",d[n]);
71 }
72 return 0;
73 }