这题相对于其他的拓扑排序,有了顺序的限制问题,总结了两种限制问题
这道题的限制是1能在前就尽量靠前,在1靠前的基础上,2能靠前也尽量靠前
刚开始我想当然的以为就是按字典序的意思,后来发现我错了,看个例子
1
4 2
4 1
3 2
如果按照字典序排序,那么答案应该是3 2 4 1
但是,如果按照题目真正的意思,答案应该是4 1 3 2
因为这样1更靠前
所以,这题建图的时候应该从v->u,然后用优先队列每次取出入度为0的id最大的点,再倒着输出
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> #include<queue> #include<iostream> #include<functional> #include<algorithm> using namespace std; typedef long long LL; const int mod=142857; const int MX=30000+5; const int INF=0x3f3f3f3f; int Path[MX],r=0; int vis[MX],A[MX],S[MX]; vector<int>G[MX]; int main(){ int T,n,m; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); r=n; memset(A,0,sizeof(A)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) G[i].clear(); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&v,&u); G[u].push_back(v); A[v]++; } priority_queue<int>work; for(int i=1;i<=n;i++){ if(A[i]==0) work.push(i); } while(!work.empty()){ int u=work.top(); work.pop(); Path[r--]=u; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; A[v]--; if(!A[v]) work.push(v); } } for(int i=1;i<=n;i++){ printf("%d%c",Path[i],i==n?'\n':' '); } } return 0; }
若题目改一下,改成按照字典序输出,那么
建图的时候边还是u->v,优先队列改成id小的先出队就行了