HDU-2066-一个人的旅行(多源到多源最短路)

Problem Description
虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。
 
Input
输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。
 
Output
输出草儿能去某个喜欢的城市的最短时间。
 
Sample Input
6 2 3 1 3 5 1 4 7 2 8 12 3 8 4 4 9 12 9 10 2 1 2 8 9 10
 
Sample Output
9


思路:两种方法,一种是直接多次Dijk算法,但要注意把各个初始节点之间的距离设为0,否则会RuntimeError。另一种比较巧妙,设一个0节点(草儿家),更新0节点到初始节点距离为0,就转化为单源到多源问题了,一个Dijk就Ok。


法一:

 1 //各个初始节点之间距离为0 
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define Inf 0x3f3f3f3f
 6 #define N 1005 
 7 using namespace std;
 8 int T,S,D,n;
 9 int G[N][N],dis[N],mark[N];
10 int s[N],e[N]; 
11 
12 void Getmap(){
13     int a,b,t;
14     n=0;
15     memset(G,Inf,sizeof(G));    
16     for(int i=0;i<T;i++){
17         scanf("%d%d%d",&a,&b,&t);
18         if(n<max(a,b)) n=max(a,b); 
19         G[i][i]=0;
20         if(t<G[a][b]) G[a][b]=G[b][a]=t;
21     }
22 
23         for(int i=0;i<S;i++)
24             scanf("%d",&s[i]);
25         for(int i=0;i<D;i++)
26             scanf("%d",&e[i]);
27         
28         for(int i=0;i<S;i++)//把初始点之间的距离更新为0
29         for(int j=i+1;j<S;j++)
30             G[s[i]][s[j]]=G[s[j]][s[i]]=0;            
31             
32 }
33  
34 void Dijk(int s){
35     int mini,p;     
36     memset(mark,0,sizeof(mark));
37     for(int i=1;i<=n;i++)
38         dis[i]=G[s][i];  
39     for(int k=0;k<n;k++){
40         mini=Inf;
41         for(int i=1;i<=n;i++)
42             if(!mark[i]&&dis[i]<mini){
43                 p=i;
44                 mini=dis[i];
45             }
46         mark[p]=1;
47         for(int i=1;i<=n;i++){
48             if(dis[i]>dis[p]+G[p][i])
49             dis[i]=dis[p]+G[p][i];
50         }    
51     }        
52 }
53 
54 int main(){
55     while(~scanf("%d%d%d",&T,&S,&D)){
56         int ans=Inf;
57         Getmap();     
58         for(int i=0;i<S;i++){        
59             Dijk(s[i]);    
60             for(int j=0;j<D;j++){
61             if(dis[e[j]]<ans) ans=dis[e[j]];
62             }    
63         }       
64         printf("%d
",ans);
65     }    
66     return 0;
67 } 

法二:

 1 //设家节点 
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define Inf 0x3f3f3f3f
 6 #define N 1005 
 7 using namespace std;
 8 int T,S,D,n;
 9 int G[N][N],dis[N],mark[N];
10 int s[N],e[N];
11 
12 void Getmap(){
13     int a,b,t;
14     n=0;
15     memset(G,Inf,sizeof(G));    
16     for(int i=0;i<T;i++){
17         scanf("%d%d%d",&a,&b,&t);
18         if(n<max(a,b)) n=max(a,b);         
19         if(t<G[a][b]) G[a][b]=G[b][a]=t;
20     }
21     for(int i=0;i<=n;i++)
22         G[i][i]=0;
23     
24     for(int i=0;i<S;i++)
25         scanf("%d",&s[i]);
26     for(int i=0;i<D;i++)
27         scanf("%d",&e[i]);
28             
29     for(int i=0;i<S;i++)//把家与各初始点间距离设为0 
30         G[0][s[i]]=G[s[i]][0]=0;                
31 }
32  
33 void Dijk(){
34     int mini,p;     
35     memset(mark,0,sizeof(mark));
36     for(int i=0;i<=n;i++)
37         dis[i]=G[0][i];    
38     for(int k=0;k<=n;k++){
39         mini=Inf;
40         for(int i=1;i<=n;i++)
41             if(!mark[i]&&dis[i]<mini){
42                 p=i;
43                 mini=dis[i];
44             }
45         mark[p]=1;
46         for(int i=1;i<=n;i++){
47             if(dis[i]>dis[p]+G[p][i])
48             dis[i]=dis[p]+G[p][i];
49         }    
50     }        
51 }
52 
53 int main(){
54     while(~scanf("%d%d%d",&T,&S,&D)){
55         int ans=Inf;
56         Getmap();
57         Dijk();    
58         for(int j=0;j<D;j++)
59             if(dis[e[j]]<ans) ans=dis[e[j]];
60          printf("%d
",ans);
61     }    
62     return 0;
63 } 
原文地址:https://www.cnblogs.com/yzhhh/p/9984556.html