[HNOI2015]菜餚製做

[HNOI2015]菜餚製做

題意:有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;
}
相關文章
相關標籤/搜索