明显还是逆拓扑,因为正序拓扑是有后效性的。
枚举第 个元素,每次都拓扑一遍,贪心使当前元素尽量靠前,复杂度 。
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;
}