题目本意是求一个拓扑序,使得1尽量靠前,1靠前的前提下2尽量靠前。。。
我们可以反向思考,建立反图,求字典序最大的拓扑序,然后反向输出即可
(对于一个点,我们将比它大且能放它后面的点都尽量放它后面了,这样理解一下)
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<queue> using namespace std; priority_queue<int> H; int du[100011],g[100011],next[100011],y[100011],ans[100011]; bool vis[100011]; int cnt,dt,tj,i,n,m,x,z,tt; bool pc; void star(int i,int j) { tt++; next[tt]=g[i]; g[i]=tt; y[tt]=j; } void Toplogical() { int l,r,x,j,k,i; pc=true; memset(vis,false,sizeof(vis)); for(i=1;i<=n;i++)if(du[i]==0)H.push(i); while(!H.empty()){ x=H.top(); vis[x]=true; H.pop(); ans[++cnt]=x; j=g[x]; while(j!=0){ k=y[j]; du[k]--; if(du[k]==0)H.push(k); j=next[j]; } } for(i=1;i<=n;i++)if(!vis[i])pc=false; } int main() { scanf("%d",&dt); for(tj=1;tj<=dt;tj++){ memset(g,0,sizeof(g)); tt=0; memset(du,0,sizeof(du)); scanf("%d%d",&n,&m); for(i=1;i<=m;i++){ scanf("%d%d",&x,&z); star(z,x); du[x]++; } while(!H.empty())H.pop(); cnt=0; Toplogical(); if(pc==false)printf("Impossible! "); else{ for(i=cnt;i>=1;i--)printf("%d ",ans[i]); printf(" "); } } }