[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;
}
相关文章
相关标签/搜索