城市平乱
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
4
- 描述
-
南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市。
他在用这N个部队维护着M个城市的治安,这M个城市分别编号从1到M。
现在,小工军师告诉南将军,第K号城市发生了暴乱,南将军从各个部队都派遣了一个分队沿最近路去往暴乱城市平乱。
现在已知在任意两个城市之间的路行军所需的时间,你作为南将军麾下最厉害的程序员,请你编写一个程序来告诉南将军第一个分队到达叛乱城市所需的时间。
注意,两个城市之间可能不只一条路。
- 输入
-
第一行输入一个整数T,表示测试数据的组数。(T<20)
每组测试数据的第一行是四个整数N,M,P,Q(1<=N<=100,N<=M<=1000,M-1<=P<=100000)其中N表示部队数,M表示城市数,P表示城市之间的路的条数,Q表示发生暴乱的城市编号。
随后的一行是N个整数,表示部队所在城市的编号。
再之后的P行,每行有三个正整数,a,b,t(1<=a,b<=M,1<=t<=100),表示a,b之间的路如果行军需要用时为t
数据保证暴乱的城市是可达的。 - 输出
- 对于每组测试数据,输出第一支部队到达叛乱城市时的时间。每组输出占一行
- 样例输入
-
1 3 8 9 8 1 2 3 1 2 1 2 3 2 1 4 2 2 5 3 3 6 2 4 7 1 5 7 3 5 8 2 6 8 2
- 样例输出
-
4
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX 0x7FFFFFFF #define N 1005 int cls[N],map[N][N],vis[N],city[101],ans[101]; int m,n,p,q; /*V为源点 */ void Dijkstra(int v) { int i,j,min,next; /* 先用v到邻接点的距离初始化cls */ for(i=1;i<=m;i++) cls[i]=map[v][i]; memset(vis,0,sizeof(vis)); vis[v]=1;//起点访问标志置1 for (i=1;i<m;i++)//无等号 { min=MAX; next=v; /*找出离集合最近的那个点next,以及该点到集合的距离min*/ for (j=1;j<=m;j++) { if(!vis[j]&&cls[j]<min) { next=j; min=cls[j]; } } vis[next]=1; for (j=1;j<=m;j++) { /*j点没有被访问过,j点和next点之间有通路,next点到j点的距离+集合到nxt的距离<集合到j的距离*/ if(!vis[j]&&map[next][j]<MAX&&(min+map[next][j])<cls[j]) cls[j]=cls[next]+map[next][j]; } } } int main() { int T,i,j;int a,b,c;int temp; scanf("%d",&T); while(T--) { temp=0x7FFFFFFF; for(i=0;i<N;i++) for(j=0;j<N;j++) map[i][j]=MAX; scanf("%d%d%d%d",&n,&m,&p,&q); /* 部队驻扎点 */ for(i=1;i<=n;i++) scanf("%d",city+i); while(p--) { scanf("%d%d%d",&a,&b,&c); if(map[a][b]>c) map[a][b]=map[b][a]=c; } for(i=1;i<=n;i++) { memset(cls,0,sizeof(cls)); Dijkstra(city[i]); ans[i]=cls[q]; //printf("%d %d %d\n",cls[q],ans[i],cls[n]); } for(i=1;i<=n;i++) if(temp>ans[i]) temp=ans[i]; printf("%d\n",temp); } return 0; } /* error: invalid types `int[int]' for array subscript 变量和数组同名 */