这题本人用spfa, 看了别的题解,确实建立一个虚拟源点真的太妙了。这里我0号点作为虚拟源点,如果某号村庄是商店,那么这个村庄到0号点的距离是0,即建立从这个村庄到0号点的一条边,令边的长度为0。 然后从0号点开始走下去就可以了。
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N = 5e5 + 5; //数组开大一点,数组的大小由id来决定
int e[N], ne[N], h[N], w[N],id;
int d[N]; bool st[N]; //本人发现st这个数组好像没什么卵用?
int n, m, q, k;
void add(int a, int b, int c){
e[id] = b;
ne[id] = h[a];
w[id] = c;
h[a] = id++;
}
queue<int> qq;
void spfa(){
qq.push(0); //从0号点开始走
//st[0] = true;
while(qq.size()){
int t = qq.front();
qq.pop();
//st[t] = false;
for(int i = h[t]; i != -1; i = ne[i]){
int k = e[i];
if(d[t] + w[i] < d[k]){
d[k] = d[t] + w[i];
qq.push(k);
//st[k] = true;
}
}
}
}
int main(){
memset(h, -1, sizeof h);
memset(d, 0x3f, sizeof d);
cin >> n >> m;
while(m--){
int a, b, c;
cin >> a >> b >> c;
add(a, b, c); //双向边,注意add两次
add(b, a, c);
}
cin >> k;
while(k--){
int x;
cin >> x;
add(0, x, 0); //如果某号村庄是商店,建立这个村庄到0号点的一条边,距离是0
add(x, 0, 0);
}
d[0] = 0;
spfa();
cin >> q;
for(int i = 0; i < q; i++){
int x;
cin >>x;
cout << d[x] << endl;
}
return 0;
}