城市平乱
时间限制: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
- 来源
- 《世界大学生程序设计竞赛高级教程·第一册》改编
- 上传者
- 张云聪
-
解题:最短路问题。。多种算法可以实现
先上dijstra算法
好吧 有点逗逼了,目的点只有一个,起点有多个,可以倒过来只求一次dijstra,把终点当起点,起点当终点,就是单源最短路径了1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <vector> 6 #include <climits> 7 #include <algorithm> 8 #include <cmath> 9 #define LL long long 10 using namespace std; 11 const int INF = INT_MAX>>2; 12 int arc[1010][1010],n,m,p,q; 13 int b[1010],d[1010]; 14 bool vis[1010]; 15 int dij(int src) { 16 int i,j,temp,index; 17 for(i = 0; i <= 1000; i++) 18 d[i] = INF; 19 d[src] = 0; 20 memset(vis,false,sizeof(vis)); 21 for(i = 0; i < m; i++) { 22 temp = INF; 23 for(j = 1; j <= m; j++) 24 if(!vis[j] && temp > d[j]) temp = d[index = j]; 25 vis[index] = true; 26 if(index == q) return d[q]; 27 for(j = 1; j <= m; j++) { 28 if(!vis[j] && d[j] > d[index]+arc[index][j]) 29 d[j] = d[index]+arc[index][j]; 30 } 31 } 32 return d[q]; 33 } 34 int main() { 35 int ks,i,j,x,y,w; 36 scanf("%d",&ks); 37 while(ks--) { 38 scanf("%d%d%d%d",&n,&m,&p,&q); 39 for(i = 0; i <= m; i++) { 40 for(j = 0; j <= m; j++) { 41 arc[i][j] = INF; 42 } 43 } 44 for(i = 0; i < n; i++) 45 scanf("%d",b+i); 46 for(i = 0; i < p; i++) { 47 scanf("%d%d%d",&x,&y,&w); 48 if(arc[x][y] > w) arc[x][y] = arc[y][x] = w; 49 } 50 int ans = dij(3),temp; 51 for(i = 1; i < n; i++) { 52 temp = dij(b[i]); 53 if(temp < ans) ans = temp; 54 } 55 printf("%d ",ans); 56 } 57 return 0; 58 }
更快的选择
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <vector> 6 #include <climits> 7 #include <algorithm> 8 #include <cmath> 9 #define LL long long 10 using namespace std; 11 const int INF = INT_MAX>>2; 12 int arc[1010][1010],n,m,p,q; 13 int b[1010],d[1010]; 14 bool vis[1010]; 15 void dij(int src) { 16 int i,j,temp,index; 17 for(i = 0; i <= 1000; i++) 18 d[i] = INF; 19 d[src] = 0; 20 memset(vis,false,sizeof(vis)); 21 for(i = 0; i < m; i++) { 22 temp = INF; 23 for(j = 1; j <= m; j++) 24 if(!vis[j] && temp > d[j]) temp = d[index = j]; 25 vis[index] = true; 26 for(j = 1; j <= m; j++) { 27 if(!vis[j] && d[j] > d[index]+arc[index][j]) 28 d[j] = d[index]+arc[index][j]; 29 } 30 } 31 } 32 int main() { 33 int ks,i,j,x,y,w; 34 scanf("%d",&ks); 35 while(ks--) { 36 scanf("%d%d%d%d",&n,&m,&p,&q); 37 for(i = 0; i <= m; i++) { 38 for(j = 0; j <= m; j++) { 39 arc[i][j] = INF; 40 } 41 } 42 for(i = 0; i < n; i++) 43 scanf("%d",b+i); 44 for(i = 0; i < p; i++) { 45 scanf("%d%d%d",&x,&y,&w); 46 if(arc[x][y] > w) arc[x][y] = arc[y][x] = w; 47 } 48 dij(q); 49 int ans = d[b[0]]; 50 for(i = 1; i < n; i++) { 51 if(d[b[i]] < ans) ans = d[b[i]]; 52 } 53 printf("%d ",ans); 54 } 55 return 0; 56 }
接着Bellman-Ford算法1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <vector> 6 #include <climits> 7 #include <algorithm> 8 #include <cmath> 9 #define LL long long 10 using namespace std; 11 const int INF = INT_MAX>>2; 12 struct{ 13 int u,v,w; 14 }e[200005]; 15 int d[1005],b[105],n,m,p,q; 16 void bf(int src){ 17 int i,j,k = p<<1; 18 bool flag; 19 for(i = 0; i <= m; i++) 20 d[i] = INF; 21 d[src] = 0; 22 for(i = 1; i < m; i++){ 23 flag = true; 24 for(j = 0; j < k; j++){ 25 if(d[e[j].v] > d[e[j].u] + e[j].w) {d[e[j].v] = d[e[j].u]+e[j].w;flag = false;} 26 } 27 if(flag) break; 28 } 29 } 30 int main(){ 31 int ks,i,j; 32 scanf("%d",&ks); 33 while(ks--){ 34 scanf("%d%d%d%d",&n,&m,&p,&q); 35 for(i = 0; i < n; i++) 36 scanf("%d",b+i); 37 for(i = 0; i < p; i++){ 38 scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); 39 e[i+p].u = e[i].v; 40 e[i+p].v = e[i].u; 41 e[i+p].w = e[i].w; 42 } 43 bf(q); 44 int ans = d[b[0]]; 45 for(i = 1; i < n; i++) 46 if(d[b[i]] < ans) ans = d[b[i]]; 47 printf("%d ",ans); 48 } 49 }
最后spfa算法1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <iostream> 6 #include <vector> 7 #include <queue> 8 #include <climits> 9 using namespace std; 10 const int INF = INT_MAX>>2; 11 struct arc { 12 int to,w; 13 }; 14 vector<arc>e[1005]; 15 int n,m,p,q,b[105]; 16 bool used[1005]; 17 int d[1005]; 18 void spfa(int src) { 19 int i,j,temp; 20 memset(used,false,sizeof(used)); 21 queue<int>qu; 22 for(i = 0; i <= m; i++) d[i] = INF; 23 d[src] = 0; 24 used[src] = true; 25 qu.push(src); 26 while(!qu.empty()) { 27 temp = qu.front(); 28 used[temp] = false; 29 qu.pop(); 30 for(i = 0; i < e[temp].size(); i++) { 31 j = e[temp][i].to; 32 if(d[j] > d[temp]+e[temp][i].w) { 33 d[j] = d[temp]+e[temp][i].w; 34 if(!used[j]) { 35 used[j] = true; 36 qu.push(j); 37 } 38 } 39 } 40 } 41 } 42 int main() { 43 int ks,i,j,u,v,w; 44 scanf("%d",&ks); 45 while(ks--) { 46 scanf("%d%d%d%d",&n,&m,&p,&q); 47 for(i = 0; i < 1005; i++) 48 e[i].clear(); 49 for(i = 0; i < n; i++) 50 scanf("%d",b+i); 51 for(i = 0; i < p; i++) { 52 scanf("%d%d%d",&u,&v,&w); 53 e[u].push_back((arc){v,w}); 54 e[v].push_back((arc){u,w}); 55 } 56 spfa(q); 57 int ans = d[b[0]]; 58 for(i = 1; i < n; i++) 59 if(ans > d[b[i]]) ans = d[b[i]]; 60 printf("%d ",ans); 61 } 62 return 0; 63 }