城市平乱
时间限制:
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算法,但是这次借着这个题学了学广搜,广搜就是需要用一个队列,他没有回溯的过程(深搜有),是一种以空间换时间的算法,在搜索中比较常用
广搜的一般结构如下:
定义一个队列;
起始点入队;
while(队列不空){
队头结点出队;
若它是所求的目标状态,跳出循环;
否则,将它扩展出的子结点,全都入队;
}
若循环中找到目标,输出结果;
否则输出无解;
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int city[1005][1005];//表示图
struct army
{
bool ishave;//ishave=1表示该村庄有军队
int len;//第i个村庄到发生暴乱城市的最短距离
}armys[1005];//军队的属性
bool visited[1005];//表示该点(村庄)有没有被搜索过
int bfs(int Q,int M)
{
int sum=999999999,temp=0;
queue<int>que;//定义一个队列
memset(visited,0,sizeof(visited));
que.push(Q);
visited[Q]=1;
while(!que.empty())
{
temp=que.front();//返回队列的队头元素
for (int i=1;i<=M;i++)
{
if(!visited[i] && city[temp][i])
{
visited[i]=1;
que.push(i);
armys[i].len=city[temp][i]+armys[temp].len;
if(armys[i].ishave && sum>armys[i].len) sum=armys[i].len;
}
}
que.pop();
}
return sum;
}
int main()
{
int T,N,M,P,Q,temp,a,b,c;//定义变量
cin>>T;
while(T--)
{
memset(armys,0,sizeof(armys));
memset(city,0,sizeof(city));
cin>>N>>M>>P>>Q;
for (int i=0;i<N;i++)
{
cin>>temp; //temp表示军队所在的村庄数
armys[temp].ishave=1;
}
for (int i=0;i<P;i++)
{
cin>>a>>b>>c;
if(city[a][b]>c||city[a][b] ==0)
{
city[a][b]=c;
city[b][a]=c;
}
}
cout<<bfs(Q,M)<<endl;
}
return 0;
}