【拓扑排序】HNOI2015菜肴制作

思路:总结题意,在满足某某一定在某某之前的约束条件下,使编号小的尽量靠前。很容易想到用小根堆求拓扑序(然而这是错的),很容易举出反例。正确的思路是求字典序最小的拓扑序,这就需要反向建图,用大根堆求反着的拓扑序。(不要忘记初始化……)

 

 

代码:(码风较差,可读性较低)

#include
#include
#include
#include
#include
#define N 100010
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define loop(i,a,b) for(int i=a;i>=b;i--)
#define edge_rep(i,a,b) for(int i=a;i;i=b)
#define clr(a) memset(a,0,sizeof(a))
using namespace std;
struct haha{
	int next,to;
}edge[N*3];
bool flag;
int d,n,m,num,cnt,sum;
int indegree[N*3],head[N*3],a[N*3];
priority_queue q;
void add(int x,int y){
	edge[++num].to=y;
	edge[num].next=head[x];
	head[x]=num;
}
int main(){
	scanf("%d",&d);
	while(d--){
		cnt=0;
		clr(indegree);clr(a);
		clr(edge);clr(head);
		while(!q.empty()) q.pop();
		scanf("%d%d",&n,&m);
		rep(i,1,m){
			int u,v;
			scanf("%d%d",&u,&v);
			add(v,u);//反向建图 
			indegree[u]++;
		}
		rep(i,1,n)
			if(!indegree[i]){
				q.push(i);
			}
		while(!q.empty()){
			int u=q.top();
			q.pop();
			edge_rep(i,head[u],edge[i].next){
				int v=edge[i].to;
				indegree[v]--;
				if(indegree[v]==0)
					q.push(v);
			}
			a[++cnt]=u;//转存到数组里逆向输出 
		}
		if(cnt==n){ 
			loop(i,cnt,1)
				printf("%d ",a[i]);
			printf("\n");
		}
		if(cnt!=n)
			printf("Impossible!\n");
	}
	return 0;
}

 

你可能感兴趣的:(OI,拓扑排序)