题解 P3393 【逃离僵尸岛】

题解 P3393 【逃离僵尸岛】

题目链接

没错这题就是单元最短路径的裸题。

同时也可以练习一下多源BFS

在处理被占领点周围的“危险点”时我们可以使用bfs,对于k个被占领点一个一个BFS显然太慢没有B格了,所以我们可以多源BFS,也就是第一次就把所有的被占领点压到队列里。

染完色以后处理每个点的权值,危险点的权值设为q,安全点的权值设为p,被占领的点权值设为一个比较大的数。

然后从点1跑最短路径就行了。

总之这是一道有点细节的模板题,要开long long不然玄学错误

代码:

/*PROPERTY OF YUANQI*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#define ll long long
#define N 200005
using namespace std;

inline ll read()
{
    ll x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x * f;
}


ll n, m, tot, head[N], P, Q, K, S, c[N], cost[N], dis[N], vis[N];
queue < int > q;
struct edge {
    ll to, next;
    edge () {
    }
    edge (int x, int y) {
        to = x, next = y;
    }
}a[2 * N];

void addedge(ll from, ll to) {
    a[++tot] = edge(to, head[from]);
    head[from] = tot;
}

void spfa() { //他死了
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for (int i = head[u]; i; i = a[i].next) {
            ll v = a[i].to;
            if (dis[u] + cost[v] < dis[v]) {
                dis[v] = dis[u] + cost[v];
                if (!vis[v]) {
                    q.push(v);
                    vis[v] = true;
                }
            }
        }
    }
}

int main()
{
    memset(dis, 0x3f3f3f3f, sizeof(dis));
    n = read(), m = read(), K = read(), S = read();
    P = read(), Q = read();
    for (int i = 1; i <= K; i++) {
        int ci = read();
        c[ci] = S + 1;
        q.push(ci);
    }
    for (int i = 1; i <= m; i++) {
        int a1 = read(), a2 = read();
        addedge(a1, a2);
        addedge(a2, a1);
    }
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        if (c[u] == 1) continue;
        for (int i = head[u]; i; i = a[i].next) {
            int v = a[i].to;
            if (!c[v]) {
                c[v] = c[u] - 1;
                q.push(v);
            }
        }
    }//多源bfs c数组表示这个点是否还能扩展
    for (int i = 1; i <= n; i++) {
        if (c[i] == S + 1) cost[i] = 1000000;
        else if (c[i]) cost[i] = Q;
        else cost[i] = P;
    }//初始化点权
    cost[1] = 0, cost[n] = 0;
    dis[1] = 0;
    q.push(1);
    vis[1] = true;
    spfa();//他死了
    cout << dis[n] << endl;
    return 0;
}

ps:最好学习一下迪杰斯特拉不然很可能被卡掉qwq
19.09.22

猜你喜欢

转载自www.cnblogs.com/YuanqiQHFZ/p/11622322.html