Description
A county consists of n cities (labeled 1, 2, …, n) connected by some bidirectional roads. Each road connects a pair of distinct cities. A robot company has built maintenance points in some cities. Now, they need your help to write a program to query the nearest maintenance point to a specific city.
Input
There will be at most 200 test cases. Each case begins with four integers n, m, s, q(2 ≤ n ≤ 104, 1 ≤ m ≤ 5 × 104, 1 ≤ s ≤ min{n, 1000},1 ≤ q ≤ min{n, 1000}), the number of cities, the number of roads, the number of cities which have maintenance points and the number of queries. Then m lines contain the descriptions of roads. Each of them contains three integers ui, vi, wi(1 ≤ ui, vi ≤ n, ui ≠ vi, 1 ≤ wi ≤ 1000), denoting there is a road of length wi which connects city ui and vi. The next line contains s integers, denoting the cities which have maintenance points. Then q lines contain the descriptions of queries. Each of them contains one integer denoting a specific city. The size of the whole input file does not exceed 6MB.
Output
For each query, print the nearest city which has a maintenance point. If there are multiple such cities, print all of them in increasing order separated by a single space. It is guaranteed that there will be at least one such city.
Sample Input
4 4 2 3 1 2 1 2 3 2 2 4 1 4 3 2 1 3 3 2 4
Sample Output
3 1 1 3
Hint
Source
湖南省第十三届大学生计算机程序设计竞赛
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<vector>
#include<algorithm>
#define INF 0x3f3f3f3f
#define N 10100
using namespace std;
int d[N],m,n,s,q,a[N],ans[N];
typedef pair<int,int> P;
struct Edge{int y,w;};
vector<Edge> g[N];
bitset<1010> p[N]; //最多1000个关键点,用关键点的序号来对应每一位
inline void dijkstra()
{
priority_queue<P,vector<P>,greater<P> > q;
for(int i=1;i<=n;i++)
{d[i]=INF;p[i].reset();}
for(int i=1;i<=s;i++) //初始时多个起点,并赋值好bitset的状态
{
q.push(P{0,a[i]});
p[a[i]][i]=1; d[a[i]]=0;
}
while (!q.empty())
{
int w=q.top().first;
int j=q.top().second;
q.pop(); if (w>d[j]) continue;
for(int k=0;k<g[j].size();k++)
{
int y=g[j][k].y;
int dist=w+g[j][k].w;
if (d[y]>dist)
{
d[y]=dist; p[y]=p[j]; //如果是大于,那么直接赋值覆盖原来的
q.push(P(d[y],y));
} else if (d[y]==dist) p[y]|=p[j]; //如果相等,那么用或来继承状态
}
}
}
int main()
{
while(~scanf("%d%d%d%d",&n,&m,&s,&q))
{
memset(g,0,sizeof(g));
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
g[u].push_back(Edge{v,w});
g[v].push_back(Edge{u,w});
}
for(int i=1;i<=s;i++)
scanf("%d",&a[i]);
sort(a+1,a+1+s); //要求关键点升序输出
dijkstra();
while(q--)
{
int x,tot=0; scanf("%d",&x);
for(int i=1;i<=s;i++)
if (p[x][i]) ans[++tot]=a[i]; //判断对应位置是否能以最短路到达
for(int i=1;i<tot;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[tot]);
}
}
return 0;
}