BZOJ 2109: [Noi2010]Plane 航空管制

明显还是逆拓扑,因为正序拓扑是有后效性的。

1 n 枚举第 i 个元素,每次都拓扑一遍,贪心使当前元素尽量靠前,复杂度 O ( n 2 l o g n )


qwq队列没清空! 我是SB! 我是SB! 我是SB! ! !

#include <cstdio>
#include <vector>
#include <queue>

const int N = 2005;

struct Node {
    int id, k;
    bool operator < (const Node &rhs) const {
        return k < rhs.k;
    }
};

std::vector<int> G[N];
std::priority_queue<Node> Q;

int cnt, ans[N], k[N], dgr[N], d[N], n;

int read() {
    int x = 0; char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
    return x;
}
void topo(int x) {
    while (!Q.empty()) Q.pop(); //一定要加! 一定要加! 一定要加!
    for (int i = 1; i <= n; ++i)
        if ((d[i] = dgr[i]) == 0 && i != x)
            Q.push((Node){i, k[i]});
    while (!Q.empty()) {
        int u = Q.top().id; Q.pop();
        if (k[u] < n - cnt) break;
        int sz = G[u].size();
        for (int i = 0; i < sz; ++i) {
            int v = G[u][i];
            if (--d[v] == 0 && v != x)
                Q.push((Node){v, k[v]});
        }
        ++cnt;
    }
}

int main() {
    n = read(); int m = read();
    for (int i = 1; i <= n; ++i) k[i] = read();
    for (int i = 1; i <= m; ++i) {
        int x = read(), y = read();
        G[y].push_back(x); ++dgr[x];
    }
    //---bzoj没有下面这一问---
    for (int i = 1; i <= n; ++i)
        if ((d[i] = dgr[i]) == 0) Q.push((Node){i, k[i]});
    while (!Q.empty()) {
        int u = Q.top().id; Q.pop();
        int sz = G[u].size();
        for (int i = 0; i < sz; ++i) {
            int v = G[u][i];
            if (--d[v] == 0) Q.push((Node){v, k[v]});
        }
        ans[++cnt] = u;
    }
    for (int i = n; i >= 1; --i) printf("%d ", ans[i]);
    puts("");
    //---bzoj没有上面这一问---
    for (int i = 1; i <= n; ++i)
        cnt = 0, topo(i), ans[i] = n - cnt;
    for (int i = 1; i <= n; ++i) printf("%d ", ans[i]);
    puts("");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Milkyyyyy/article/details/81394453