• 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 } 
  • 相关阅读:
    IE6-IE11兼容性问题列表及解决办法
    EJB--事务管理 .
    JDBC批处理---(java 对数据库的回滚) .
    redisb并发访问慢出现的问题
    redis其他问题
    多线程实现服务器端接收连接
    序列化作用
    redis的key过期时间
    nginx负载均衡和反向代理有什么区别
    nginx的负载均衡和反响代理配置
  • 原文地址:https://www.cnblogs.com/yzhhh/p/9984556.html
Copyright © 2020-2023  润新知