拓扑排序 tzoj6082
反向拓扑:(正向行不通,这题要求序号小的尽量排前面,而不是要求字典序)
比如输入:
1
3 1
3 1
则仅有3指向1,正向拓扑结果是2,3,1;但并不是正确结果
题目要求序号小尽量排前面,可以是3,1,2;这样1就往前排了
所以用反向拓扑,把图画反,用优先队列(大到小)进行拓扑(保证小的在后),最后倒序输出即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int n,m; vector<int>edge[30005]; int in[30005]; map<int,int>mp; void topu() { priority_queue<int>q; for(int i=1;i<=n;i++) //n 节点的总数 if(in[i]==0) q.push(i); //将入度为0的点入队列 vector<int>ans; //ans 为拓扑序列 while(!q.empty()) { int p=q.top(); q.pop(); // 选一个入度为0的点,出队列 ans.push_back(p); for(int i=0;i<edge[p].size();i++) { int y=edge[p][i]; in[y]--; if(in[y]==0) q.push(y); } } printf( "%d",ans[ans.size()-1] ); for(int i=ans.size()-2;i>=0;i--) printf( " %d",ans[i] ); printf("\n"); } int main() { int i,t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); mp.clear(); memset(in,0,sizeof(in)); for(i=1;i<=n;i++)edge[i].clear(); while(m--){ int x,y; scanf("%d%d",&x,&y); in[x]++; edge[y].push_back(x); } topu(); } return 0; }