看起来似乎是个水水的拓扑排序+堆,然而并不对,因为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 }