題意:有n個數排成一列,給定m個限制(x,y),表示x應在y的前面,規定對於x1,x2,x1<x2,每一個x1若是不存在一條限制路徑(每一個限制連一條(x,y)x=>y的邊),則x1應排在x2前面,求最終排列c++
算法:拓撲排序算法
咱們若是單純的找一個字典序最小的限制隊列,這很顯然是一個拓撲板子spa
可是這很顯然沒有那麼簡單,你仔細思考會發現,正着搞有不少的後效性,很是難搞blog
因此,正難則反,咱們應該想可不能夠反着建圖排序
咱們發現,對於最後一位,確定是沒有限制的最大的那個數,而後把對於這個數有限制的數度數減1,以此類推,咱們會發現這樣很是正確,並無後效性的影響。隊列
CODE:ci
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define MAXN 100050 using namespace std; struct zlk{ int x; bool operator <(zlk a) const{ return x<a.x; } }; priority_queue<zlk> Q; int de[MAXN],n,fir[MAXN],nxt[MAXN],to[MAXN],m,t,tot,q[MAXN],cnt; void ade(int x,int y){ to[++tot]=y; nxt[tot]=fir[x]; fir[x]=tot; } int main(){ cin>>t; while(t--){ tot=0; memset(fir,0,sizeof(fir)); memset(de,0,sizeof(de)); scanf("%d%d",&n,&m); rep(i,1,m){ int x,y; scanf("%d%d",&x,&y); ade(y,x); de[x]++; } rep(i,1,n) if(!de[i]) Q.push((zlk){i}); cnt=0; while(!Q.empty()){ int x=Q.top().x; Q.pop(); q[++cnt]=x; for(int k=fir[x];k;k=nxt[k]){ de[to[k]]--; if(!de[to[k]]) Q.push((zlk){to[k]}); } } if(cnt!=n){puts("Impossible!"); continue;} while(cnt) cout<<q[cnt--]<<" "; cout<<endl; } return 0; }