BZOJ 3875: [Ahoi2014&Jsoi2014]骑士游戏

首先正着搜是错的。。因为搜索的顺序会影响结果。。
那么就把所有点按法术攻击的大小都加入小根堆,每次取出最小的,那么解决它就只需要用法术攻击了。因为肯定存在解决它的儿子用法术攻击的情况,而且需要的花费比解决它的法术攻击还大,那必然用一次法术攻击解决它,不过存在当它没有儿子时,就把法术攻击和普通攻击取个min就对了。
这样就相当于在一个DAG上跑dijkstra了,当它们的父亲度数也为 \(0\) 了就可以更新。
复杂度 \(O(n \log n)\)

#include <bits/stdc++.h>
#define ll long long

namespace IO {
    const int MAXSIZE = 1 << 20;
    char buf[MAXSIZE], *p1, *p2;
    #define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin), p1 == p2) ? EOF : *p1++)
    void read() {}
    template<typename T, typename ... T2>
    inline void read(T &x, T2 &... oth) {
        x = 0; T f = 1; char ch = gc();
        while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = gc(); }
        while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = gc(); }
        x *= f;
        read(oth...);
    }
}

const int N = 2e5 + 7;
const int M = 1e6 + 7;
int head1[N], head2[N], cnt = 1, n, deg[N];
ll dis[N], a[N];
struct E {
    int v, ne;
} e[M << 1];

void add(int u, int v, int *head) {
    e[++cnt].v = v; e[cnt].ne = head[u]; head[u] = cnt;
}

struct Node {
    int u;
    ll d;
    Node(int _u = 0, ll _d = 0): u(_u), d(_d) {}
    bool operator < (const Node &p) const {
        return d > p.d;
    }
};
std::priority_queue<Node> que;
bool done[N];

int main() {
    IO::read(n);
    for (int i = 1, x; i <= n; i++) {
        IO::read(a[i], dis[i], deg[i]);
        for (int j = 1; j <= deg[i]; j++) {
            int x;
            IO::read(x);
            add(i, x, head1);
            add(x, i, head2);
        }
        if (!deg[i]) dis[i] = std::min(dis[i], a[i]);
        que.push(Node(i, dis[i]));
    }
    while (!que.empty()) {
        Node p = que.top(); que.pop();
        int u = p.u;
        if (u == 1) break;
        if (done[u]) continue;
        done[u] = 1;
        for (int i = head2[u]; i; i = e[i].ne) {
            int fa = e[i].v;
            deg[fa]--;
            if (!deg[fa] && !done[fa]) {
                ll temp = a[fa];
                for (int j = head1[fa]; j; j = e[j].ne)
                    temp += dis[e[j].v];
                if (temp < dis[fa]) {
                    dis[fa] = temp;
                    que.push(Node(fa, dis[fa]));
                }
            }
        }
    }
    printf("%lld\n", dis[1]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/12296260.html