有 NN 个村庄,编号 11 到 NN。
村庄之间有 MM 条无向道路,第 ii 条道路连接村庄 aiai 和村庄 bibi,长度是 cici。
所有村庄都是连通的。
共有 KK 个村庄有商店,第 jj 个有商店的村庄编号是 xjxj。
然后给出 QQ 个询问,第 kk 个询问给出一个村庄的编号 ykyk,问该村庄距离最近的商店有多远?

输入格式

第一行包含两个整数 N,MN,M。
接下来 MM 行,每行包含三个整数 ai,bi,ciai,bi,ci,表示第 ii 条道路连接村庄 aiai 和村庄 bibi,长度是 cici。
再一行包含整数 KK。
接下来 KK 行,每行包含一个整数 xjxj,表示第 jj 个有商店的村庄编号是 xjxj。
再一行包含整数 QQ。
接下来 QQ 行,每行包含一个整数 ykyk,表示询问编号为 ykyk 的村庄与其距离最近的商店之间的距离。

输出格式

对于每个询问,输出该询问的结果。

数据范围

2≤N≤1052≤N≤105,
N−1≤M≤min(N(N−1)2,105)N−1≤M≤min(N(N−1)2,105),
1≤Q≤1051≤Q≤105,
1≤K≤N1≤K≤N,
1≤ci≤100001≤ci≤10000

输入样例:

7 7 1 2 5 1 4 3 2 3 2 2 5 1 3 6 7 5 6 8 6 7 6 3 7 5 4 7 1 2 3 4 5 6 7

输出样例:

3 1 3 0 0 6 0


  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N = 100010, M = 3 * N;
  6. int h[N], e[M], ne[M], w[M], idx;
  7. int dist[N];
  8. bool st[N];
  9. int q[N]; //队列
  10. int n, m;
  11. void add(int a, int b, int c) {
  12. e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
  13. }
  14. void spfa() {
  15. memset(dist, 0x3f, sizeof dist);
  16. int hh = 0, tt = 1;
  17. dist[0] = 0;
  18. st[0] = true; //加入到队列
  19. while (hh != tt) {
  20. int t = q[hh ++];
  21. if (hh == N) hh = 0;
  22. st[t] = false;
  23. for (int i = h[t]; i != -1; i = ne[i]) {
  24. int j = e[i];
  25. if (dist[j] > dist[t] + w[i]) {
  26. dist[j] = dist[t] + w[i];
  27. if (!st[j]) {
  28. q[tt ++] = j;
  29. st[j] = true;
  30. if (tt == N) tt = 0;
  31. }
  32. }
  33. }
  34. }
  35. }
  36. int main() {
  37. cin >> n >> m;
  38. memset(h, -1, sizeof h);
  39. for (int i = 1; i <= m; ++i) {
  40. int a, b, c;
  41. cin >> a >> b >> c;
  42. add(a, b, c); //无向边
  43. add(b, a, c);
  44. }
  45. cin >> m;
  46. //超级源点到商店村庄的距离设置为0
  47. for (int i = 1; i <= m; ++i) {
  48. int a;
  49. cin >> a;
  50. add(0, a, 0);
  51. }
  52. spfa();
  53. cin >> m;
  54. for (int i = 1; i <= m; ++i) {
  55. int a;
  56. cin >> a;
  57. cout << dist[a] << endl;
  58. }
  59. return 0;
  60. }