题面
题解
题目很简单, 用优先队列维护拓扑序即可
但是他要我们求的东西比较诡异, 导致贪心的策略会不同
对于第一问, 我们一般的思路是直接维护正的拓扑序, 每次选最小的更新
但这样不一定是最优的, 因为选择了当前最小的可能使得更小的拓扑序排在后面, 这样字典序就不一定是最小的了
所以我们维护反的拓扑序, 每次选最大的更新
第二问可以直接用大根堆维护正的拓扑序就行了
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
const int N = 200005;
using namespace std;
int n, a[N], deg[N], in[N], ans[N], head[N], cnt;
struct edge { int to, nxt; } e[N];
priority_queue<int> q;
template < typename T >
inline T read()
{
T x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * w;
}
inline void adde(int u, int v) { e[++cnt] = (edge) { v, head[u] }, head[u] = cnt; }
int main()
{
n = read <int> ();
for(int i = 1; i <= n; i++)
{
a[i] = read <int> ();
if(a[i]) adde(a[i], i), deg[a[i]]++, in[i]++;
}
cnt = n;
for(int i = 1; i <= n; i++)
if(!deg[i]) q.push(i);
while(!q.empty())
{
int u = q.top(); q.pop();
ans[u] = cnt--;
if(!(--deg[a[u]])) q.push(a[u]);
}
for(int i = 1; i <= n; i++)
printf("%d%c", ans[i], i == n ? '
' : ' ');
cnt = 0;
for(int i = 1; i <= n; i++)
if(!in[i]) q.push(i);
while(!q.empty())
{
int u = q.top(); q.pop();
ans[u] = ++cnt;
for(int v, i = head[u]; i; i = e[i].nxt)
{
v = e[i].to;
q.push(v);
}
}
for(int i = 1; i <= n; i++)
printf("%d%c", ans[i], i == n ? '
' : ' ');
return 0;
}