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
题目大意:有n个城市,m条边将一些城市连接起来,现在有s个城市维护点,q次查询,现在对于每一次查询的城市,输出离他最近的城市维护点,如果有多个则按递增顺序打印。
思路: 把s个城市维护点当起点搜一下最短路,其中用bitset来维护其他城市距离维护点最近的那个起点,对于城市x来说,若有多个起点城市到它的最短距离是相等的就用或运算将之存在bitset,否则直接将最短的那一个维护点赋值给x
代码上也做了一些注释(如果对于bitset不是很熟悉的可以向大家推荐一篇感觉还不错的博客。http://www.cppblog.com/ylfeng/archive/2010/03/26/110592.html)
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<bitset> 5 #include<vector> 6 #include<queue> 7 8 using namespace std; 9 const int INF = 1 << 28; 10 const int maxn = 20005; 11 struct node { 12 int to, cost; 13 node() {} 14 node(int a, int b) :to(a), cost(b) {} 15 bool operator<(const node&a)const { 16 return cost > a.cost; 17 } 18 }; 19 vector<node>e[maxn]; 20 bitset<1005>bt[maxn]; 21 int n, m, s, q; 22 int dis[maxn], cha[maxn], vis[maxn]; 23 void Dijkstra() 24 { 25 priority_queue<node>Q; 26 for (int i = 1; i <= n; i++) { 27 dis[i] = INF; bt[i].reset();//初始化距离和清空bitset表 28 vis[i] = 0; 29 } 30 for (int i = 1; i <= s; i++) { 31 dis[cha[i]] = 0; 32 Q.push(node(cha[i], dis[cha[i]])); 33 bt[cha[i]][i] = 1;//bt[i][j] = 1 代表第i个城市最近的城市维护点是第j个 34 } 35 while (!Q.empty()) { 36 node t = Q.top(); Q.pop(); 37 if (vis[t.to])continue; 38 vis[t.to] = 1;//对于每一个点我们只需要以他为起点遍历一次就ok,避免大量的重复计算 39 for (int i = 0; i < e[t.to].size(); i++) { 40 int tmp = e[t.to][i].to; 41 int ct = e[t.to][i].cost; 42 if (dis[tmp] > dis[t.to] + ct) { 43 dis[tmp] = dis[t.to] + ct; 44 Q.push(node(tmp, dis[tmp])); 45 bt[tmp] = bt[t.to];//如果有比当前更近的城市维护点则将更近的维护点赋值给现在的点 46 } 47 else if (dis[tmp] == (dis[t.to] + ct)) 48 bt[tmp] |= bt[t.to];//如果有多个城市维护点的距离相同就取或赋值 49 } 50 } 51 } 52 int main() 53 { 54 while (scanf("%d%d%d%d", &n, &m, &s, &q) != EOF) { 55 for (int i = 1; i <= n; i++)e[i].clear(); 56 for (int a, b, c, i = 0; i < m; i++) { 57 scanf("%d%d%d", &a, &b, &c); 58 e[a].push_back(node(b, c)); 59 e[b].push_back(node(a, c)); 60 } 61 for (int i = 1; i <= s; i++)scanf("%d", &cha[i]); 62 sort(cha + 1, cha + s + 1);//因为题目要我们如果有多个点满足要求,则递增输出,所以我们可以事先排个序 63 Dijkstra(); 64 int x; 65 while (q--) { 66 int a[1010], cnt = 0; 67 scanf("%d", &x); 68 for (int i = 1; i <= s; i++) 69 if (bt[x][i])//对于s个城市维护点来说,若bt[x][i]==1则代表第i个城市到x的距离是最近的 70 a[++cnt] = cha[i]; 71 for (int i = 1; i < cnt; i++) 72 printf("%d ", a[i]);//最后按格式输出即可 73 printf("%d ", a[cnt]); 74 } 75 } 76 return 0; 77 }