题目大意:
解题思路:
将所有被控制的点视为点
0
0
0,将所有与被控制的点连边的点连向
0
0
0,暂定所有边权为
1
1
1
然后以
0
0
0为起点跑一遍
d
i
j
dij
dij,如果
d
i
s
[
i
]
≤
s
dis[i]\leq s
dis[i]≤s,那么
i
i
i是危险点将与
i
i
i连边的边权定为
Q
Q
Q,与被控制点的连边边权定为
i
n
f
inf
inf,其它边为
P
P
P
特殊的,起点为
1
o
r
n
1\ or\ n
1 or n或终点为
1
o
r
n
1\ or\ n
1 or n的边边权为0
或者以每个被控制点为起点 b f s bfs bfs,第 S S S层或 S S S以下的都为危险点
A c c e p t e d c o d e : Accepted\ code: Accepted code:
#include<queue>
#include<cstdio>
#define int long long
using namespace std;
const int N = 100005;
const long long inf = 1e17;
priority_queue < pair<int, int> > q;
struct Line {
int to, w, next;
}e[N<<2];
int n, m, k, s, cnt;
int a[N], d[N], dis[N], vis[N], last[N];
inline void add(int x, int y) {
e[++cnt] = (Line){y, 1ll, last[x]}; last[x] = cnt;
e[++cnt] = (Line){x, 1ll, last[y]}; last[y] = cnt;
}
void dij(int S) {
for (int i = 1; i <= n; ++i) dis[i] = inf, vis[i] = 0;
vis[0] = 0;
while (q.size()) q.pop();
q.push(make_pair(0, S)); dis[S] = 0;
while (q.size()) {
int x = q.top().second; q.pop();
if (vis[x]) continue;
vis[x] = 1;
for (int i = last[x]; i; i = e[i].next) {
int y = e[i].to;
if (dis[y] > dis[x] + e[i].w) {
dis[y] = dis[x] + e[i].w;
if (!vis[y]) q.push(make_pair(-dis[y], y));
}
}
}
}
signed main() {
int P = 0, Q = 0;
scanf("%lld %lld %lld %lld", &n, &m, &k, &s);
scanf("%lld %lld", &P, &Q);
for (int i = 1, WX = 0; i <= k; ++i)
scanf("%lld", &WX), a[WX] = 1;
for (int i = 1, x = 0, y = 0; i <= m; ++i) {
scanf("%lld %lld", &x, &y);
if (a[x] && a[y]) continue;
if (a[x]) add(0, y);
else if (a[y]) add(0, x);
else add(x, y);
}
dij(0);
for (int i = 1; i <= n; ++i)
if (dis[i] <= s) d[i] = 1;
for (int i = 1; i <= cnt; ++i) {
if (d[e[i].to]) e[i].w = Q;
else if (a[e[i].to]) e[i].w = inf;
else e[i].w = P;
e[i].w = (e[i].to == 1 || e[i].to == n) ? 0 : e[i].w;
//之前以为数据保证n点不是危险点,然后就WA了
//n有可能是危险点,但是题目告诉我们就算n在被控制点的传染范围内
//n也不是危险点
}
dij(1);
printf("%lld\n", dis[n]);
}