[CF825E] Minimal Labels - 拓扑排序,堆,贪心
[CF825E] Minimal Labels - 拓扑排序,堆,贪心
Description
有一个 \(n\) 个点, \(m\) 条边的有向图。你需要输出一个 \(1\) 到 \(n\) 的全排列 \(label\),使得:如果从点 \(v\) 到点 \(u\) 有一条有向边,那么必须满足 \(label_v < label_u\)。在所有满足要求的全排列中,需要满足答案的字典序最小
Solution
建反图后,类似拓扑排序去贪心,每次挑选反图中没有入度的点,给编号最大的分配一个最大的值,用一个大顶堆维护即可
#include
using namespace std;
#define int long long
const int N = 1e6 + 5;
int deg[N], vis[N], n, m, ans[N], ind;
vector 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, less> 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;
}