解题:CF825E Minimal Labels

题面

看起来似乎是个水水的拓扑排序+堆,然而并不对,因为BFS拓扑排序的话每次只会在“当前”的点中排出一个最小/大的字典序,而我们是要一个确定的点的字典序尽量小。正确的做法是反向建图,之后跑一个字典序最大的拓扑序。因为拓扑排序是一个类似于“解锁”的过程,它具有后效性,我们并不能直接贪心来做,需要反过来做消除后效性。

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=100005;
 7 int deg[N],mark[N];
 8 int p[N],noww[N],goal[N];
 9 int n,m,t1,t2,cnt,num;
10 priority_queue<int> hp;
11 void link(int f,int t)
12 {
13     noww[++cnt]=p[f];
14     goal[cnt]=t,p[f]=cnt;
15 }
16 int main ()
17 {
18     scanf("%d%d",&n,&m),num=n;
19     for(int i=1;i<=m;i++)
20     {
21         scanf("%d%d",&t1,&t2);
22         link(t2,t1),deg[t1]++;
23     }
24     for(int i=1;i<=n;i++)
25         if(!deg[i]) hp.push(i);
26     while(!hp.empty())
27     {
28         int tn=hp.top(); 
29         hp.pop(); mark[tn]=num--;
30         for(int i=p[tn];i;i=noww[i])
31             if(!(--deg[goal[i]])) hp.push(goal[i]);
32     }
33     for(int i=1;i<=n;i++) printf("%d ",mark[i]);
34     return 0;
35 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9709085.html