HDU - 2066 最短路+加一个节点

一个图上,有M条边,Z个出发点,Y个终止点。求一条最短路,其中起点是Z中的任意一点,终点是Y中任意一点。

Input

输入数据有多组,输入直到文件结束。

每组的第一行是三个整数M,Z,Y

接着有M行,每行有三个整数a,b,w,表示a,b之间存在一条长度为w的边 (1=<(a,b)<=1000,w原题干未给范围c++ int够用),可能存在重边,边为双向边。

接着的第M+1行有Z个数,表示起点标号

接着的第M+2行有Y个数,表示终点标号

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

代码(邻接矩阵):

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<vector>
  7 using namespace std;
  8 const int maxn=1005;
  9 typedef long long ll;
 10 #define INF 0x3f3f3f3f
 11 struct shudui1
 12 {
 13     ll start,value;
 14     bool operator < (const shudui1 q)const
 15     {
 16         return value<q.value;
 17     }
 18 } str1;
 19 struct shudui2
 20 {
 21     ll start,value;
 22 } str2;
 23 ll v1[maxn],v2[maxn],v[maxn],k[maxn][maxn];
 24 priority_queue<shudui1>r;
 25 void JK(ll maxx)
 26 {
 27     memset(v,INF,sizeof(v));
 28     v[0]=0;
 29     str1.start=0;
 30     str1.value=0;
 31     r.push(str1);
 32     while(!r.empty())
 33     {
 34         ll x,y;
 35         str1=r.top();
 36         r.pop();
 37         x=str1.start;
 38         y=str1.value;
 39         if(v[x]<y) continue;
 40         //说明在这个点再此之后又入队了
 41         //此次出队的并不是s到这个点的最短路,
 42         //所以在这次更新前点v所连的点已经更过一次了
 43         //所以后面也不会进行松弛操作
 44         for(ll i=0; i<=maxx; ++i)
 45         {
 46             if((v[x]+k[x][i]<v[i]))
 47             {
 48                 v[i]=v[x]+k[x][i];
 49                 str1.start=i;
 50                 str1.value=v[i];
 51                 r.push(str1);
 52             }
 53         }
 54     }
 55 }
 56 
 57 int main()
 58 
 59 {
 60 
 61     ll n,m,p,a,b,c;
 62 
 63     while(scanf("%lld %lld %lld",&n,&m,&p)!=EOF)
 64 
 65     {
 66 
 67         memset(k,INF,sizeof(k));
 68 
 69         ll maxx=n;
 70 
 71         for(ll i=1; i<=n; i++)
 72 
 73         {
 74 
 75             scanf("%lld %lld %lld",&a,&b,&c);
 76 
 77             maxx=max(maxx,max(a,b));  //记录顶点上限
 78 
 79             k[a][b]=min(c,k[a][b]);  //保存最小边权
 80 
 81             k[b][a]=min(c,k[a][b]);
 82 
 83         }
 84 
 85         for(ll i=0; i<m; i++)
 86 
 87         {
 88 
 89             scanf("%lld",&a);
 90 
 91             k[a][0]=k[0][a]=0;
 92 
 93         }
 94 
 95         for(ll i=0; i<p; i++)
 96 
 97             scanf("%lld",&v2[i]);
 98 
 99         ll minn=INF;
100 
101         JK(maxx);
102 
103         for(ll j=0; j<p; j++)  //找到最小路径
104 
105             if(v[v2[j]]<minn)
106 
107                 minn=v[v2[j]];
108 
109         printf("%lld\n",minn);
110 
111     }
112 
113 }
View Code

 

代码(邻接表)+注释:

  1 /*
  2 这道题首先不能暴力枚举起点和终点,所以floyd就不用再用了
  3 
  4 我们只需要弄一个新节点(我代码中是maxx),让起点和新节点连一条边,边的距离为0,这样的话只需要跑一边迪杰斯特拉算法后,在v数组中枚举终点,取最小值就可以了
  5 
  6 错了这么多次,才发现原来我是没有清空vector容器。。。
  7 用邻接表存图是不用考虑有重边这个问题的
  8 
  9 */
 10 #include<stdio.h>
 11 #include<string.h>
 12 #include<iostream>
 13 #include<algorithm>
 14 #include<queue>
 15 #include<vector>
 16 using namespace std;
 17 const int maxn=1005;
 18 typedef long long ll;
 19 #define INF 0x3f3f3f3f
 20 struct shudui1
 21 {
 22     ll start,value;
 23     bool operator < (const shudui1 q)const
 24     {
 25         return value<q.value;
 26     }
 27 } str1;
 28 struct shudui2
 29 {
 30     ll start,value;
 31 } str2;
 32 ll v1[maxn],v2[maxn],v[maxn];
 33 priority_queue<shudui1>r;
 34 vector <shudui2>w[2005];
 35 void JK(ll s)
 36 {
 37     memset(v,INF,sizeof(v));
 38     v[s]=0;
 39     str1.start=s;
 40     str1.value=0;
 41     r.push(str1);
 42     while(!r.empty())
 43     {
 44         ll x,y;
 45         str1=r.top();
 46         r.pop();
 47         x=str1.start;
 48         y=str1.value;
 49         if(v[x]<y) continue;
 50         //说明在这个点再此之后又入队了
 51         //此次出队的并不是s到这个点的最短路,
 52         //所以在这次更新前点v所连的点已经更过一次了
 53         //所以后面也不会进行松弛操作
 54         ll len=w[x].size();
 55         for(ll i=0; i<len; ++i)
 56         {
 57             str2=w[x][i];
 58             if((v[x]+str2.value<v[str2.start]))
 59             {
 60                 v[str2.start]=v[x]+str2.value;
 61                 str1.start=str2.start;
 62                 str1.value=v[str2.start];
 63                 r.push(str1);
 64             }
 65         }
 66     }
 67 }
 68 int main()
 69 {
 70     ll a,z,y,d,f,g;
 71     while(~scanf("%lld%lld%lld",&a,&z,&y))
 72     {
 73         ll maxx=0;
 74         while(a--)
 75         {
 76             scanf("%lld%lld%lld",&d,&f,&g);
 77             maxx=max(maxx,max(d,f));
 78             str2.start=f;
 79             str2.value=g;
 80             w[d].push_back(str2);
 81             str2.start=d;
 82             str2.value=g;
 83             w[f].push_back(str2);
 84         }
 85         maxx+=1;
 86         for(ll i=1; i<=z; ++i)
 87         {
 88             scanf("%lld",&v1[i]);
 89             str2.start=v1[i];
 90             str2.value=0;
 91             w[maxx].push_back(str2);
 92             str2.start=maxx;
 93             str2.value=0;
 94             w[v1[i]].push_back(str2);
 95         }
 96 
 97         for(ll i=1; i<=y; ++i)
 98             scanf("%lld",&v2[i]);
 99         ll minn=INF;
100 
101         JK(maxx);
102         for(ll j=1; j<=y; ++j)
103         {
104             minn=min(minn,v[v2[j]]);
105         }
106 
107         printf("%lld\n",minn);
108         for(int i=1;i<=maxx;++i)
109         {
110             w[i].clear();
111         }
112     }
113     return 0;
114 }

 

posted @ 2020-04-02 10:11  kongbursi  阅读(130)  评论(0编辑  收藏  举报