题目描述:输入的第一行有三个数,T,S,D,T表示一共有多少条线路,S表示起点的个数,D表示终点的个数,接下来就是输入T条路的信息了,要你判断从多个起点中任意一个到多个终点中的任意的一个的最短距离是多少。
解题报告:这题与其他的题目最大的不同就是这题的起点和终点都有多个,不然就可以用迪杰斯特拉来解了,但是虽然这题有多个起点和多个终点,我们可不可以把它转化成用迪杰斯特拉解决的问题的类型呢,即转化成单个起点的问题呢? 答案是可以的,我们完全可以假设一个虚拟的起点和一个虚拟的终点,即将原来的N个点的图再加两个,变成N+2 个点图,一个起点一个终点,我们可以令实际上的起点到虚拟的起点的距离是一个定值,同理,令所有的终点到虚拟的终点的距离也是一个定值,这样就可以轻松的转化成用单源的最短路问题了,用迪杰斯特拉即可解出。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 const int MAX = 0xfffff,SIZE = 1000+5; 5 int T1,S,D,map[SIZE][SIZE],f,T[SIZE],visit[SIZE]; 6 int main() { 7 int a,b,len,x,y; 8 while(scanf("%d%d%d",&T1,&S,&D)!=EOF) { 9 memset(map,0x3f,sizeof(map)); 10 memset(T,0x3f,sizeof(T)); 11 printf("%d ",T[0]); 12 f = 0; 13 for(int i = 1;i<=T1;++i) { 14 scanf("%d%d%d",&a,&b,&len); 15 f = std::max(a,f); //找到编号最大的点以确定范围 16 f = std::max(b,f); 17 map[a][b] = map[b][a] = std::min(len,map[a][b]); 18 //如果有多条路径,取权值最小的 19 } 20 for(int i = 1;i<=S;++i) { //增加虚拟起点到草儿家附近的城市的距离 21 scanf("%d",&a); 22 map[0][a] = map[a][0] = 1; 23 } 24 f++; //增加一个虚拟的终点 25 for(int i = 1;i<=D;++i) { //增加虚拟起点到草儿想去的城市的距离 26 scanf("%d",&a); 27 map[f][a] = map[a][f] = 1; 28 } 29 int s = 0; 30 T[s] = 0; 31 memset(visit,0,sizeof(visit)); 32 while(1) { 33 if(s == f) 34 break; 35 for(int i = 0;i<=f;++i) 36 if(!visit[i]&&(T[i]>(T[s]+map[s][i]))) 37 T[i] = T[s]+map[s][i]; 38 visit[s] = 1; 39 s = f+1; 40 bool flag = 1; 41 for(int i = 0;i<=f;++i) 42 if(!visit[i]&&T[i]<T[s]) { 43 s = i; 44 flag = 0; 45 } 46 if(flag) 47 break; 48 } 49 printf("%d ",T[f]-2); 50 } 51 return 0; 52 }