城市平乱
时间限制: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
这就是一个的寻路算法,这里只需要将暴乱的城市设为开始城市时间就是权值,遍历完所有的城市之后在有部队的城市找最小值,然后输出这个城市的编号。我的寻路算法用的是SPFA算法
全部代码如下
//#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<iterator>
#include<queue>
#include<string.h>
using namespace std;
#define MAX 1005
int N, M, P, Q;
int dis[MAX][MAX], trop[MAX];
int spfa(int s)
{
queue<int> que;//没有遍历的城市入队
int city[MAX] = { 0 }, path[MAX] = { 0 }, visit[MAX] = { 0 },smin = 0;
memset(path, 2, sizeof(path));//将初始值最大化
que.push(s);path[s] = 0;visit[s] = 1;//将第一个城市入队同时访问状态设为1
while (!que.empty())
{
int temp = que.front();que.pop();//取出头结点的城市
for (int i = 1;i <= M;i++)
{
if (path[temp] + dis[temp][i]<path[i])//路径进行松弛操作更新为最短
{
path[i] = path[temp] + dis[temp][i];
if (!visit[i])//如果没有被访问就入队
{
que.push(i);
visit[i] = 1;
}
}
if (trop[i] == 1)
{
smin = (smin != 0 ? smin : path[i]) < path[i] ? smin : path[i];//找最短的时间
}
}
}
cout << smin << endl;
return 0;
}
int main()
{
freopen("data.in", "r", stdin);
int t;
cin >> t;
while (t--)
{
memset(dis, 2, sizeof(dis));
memset(trop, 0, sizeof(trop));
cin >> N >> M >> P >> Q;
for (int i = 0;i < N;i++)
{
int num;
cin >> num;
trop[num] = 1;
}
for (int i = 0;i < P;i++)
{
int a, b, t;
cin >> a >> b >> t;
if (dis[a][b] > t)
{
dis[a][b] = dis[b][a] = t;//虽然两个城市之间路径不止一条 只需要存入时间最短的一条
}
}
spfa(Q);
}
return 0;
}