[CF825E] Minimal Labels - 拓扑排序,堆,贪心
Description
有一个 (n) 个点, (m) 条边的有向图。你需要输出一个 (1) 到 (n) 的全排列 (label),使得:如果从点 (v) 到点 (u) 有一条有向边,那么必须满足 (label_v < label_u)。在所有满足要求的全排列中,需要满足答案的字典序最小
Solution
建反图后,类似拓扑排序去贪心,每次挑选反图中没有入度的点,给编号最大的分配一个最大的值,用一个大顶堆维护即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 5;
int deg[N], vis[N], n, m, ans[N], ind;
vector<int> g[N];
signed main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
g[v].push_back(u);
deg[u]++;
}
priority_queue<int, vector<int>, less<int>> heap;
for (int i = 1; i <= n; i++)
if (deg[i] == 0)
heap.push(i);
while (heap.size())
{
int p = heap.top();
heap.pop();
ans[p] = n - ind;
ind++;
for (int q : g[p])
{
deg[q]--;
if (deg[q] == 0)
heap.push(q);
}
}
for (int i = 1; i <= n; i++)
cout << ans[i] << " ";
cout << endl;
}