poj 3687 topsort(按顺序放球)

题意:n个重量为1~n的球,要用1-n给这些球编号。给定一些编号间的重量比较关系,在符合条件的前提下使得编号小的球重量小。(先保证1号球最轻,其次2号……)

思路:拓扑排序,注意根据题的要求,要先保证1号球最轻,如果我们由轻的向重的连边,然后我们依次有小到大每次把重量分给一个入度为0的点,那么在拓扑时我们面对多个入度为0的点,我们不知道该把最轻的分给谁才能以最快的速度找到1号(使1号入度为0),并把当前最轻的分给1号。所以我们要由重的向轻的连边,然后从大到小每次把一个重量分给一个入度为0的点。这样我们就不用急于探求最小号。我们只需要一直给最大号附最大值,尽量不给小号赋值,这样自然而然就会把轻的重量留给小号。题目中可能有重边,用邻接矩阵存储必须注意,但是用邻接表存储恰恰避免了处理邻边的问题(http://www.cnblogs.com/rainydays/archive/2011/07/20/2112047.html)

#include <stdio.h>
#include <string.h>
#define N 205
#define M 40005
struct edge{
	int y,next;
}e[M];
int n,m,T,top;
int d[N],first[N],res[N];
void add(int x,int y){
	e[top].y = y;
	e[top].next = first[x];
	first[x] = top++;
}
void topsort(){
	int i,j,k;
	for(i = n;i>=1;i--){
		for(j = n;j>=1;j--)
			if(!d[j]){
				d[j]--;
				break;
			}
		if(!j){
			printf("-1\n");
			return;
		}
		res[j] = i;
		for(k = first[j];k!=-1;k=e[k].next)//如果有重边也一次全部消除掉了
			d[e[k].y]--;
	}
	for(i = 1;i<=n;i++)
		printf("%d ",res[i]);
	putchar('\n');
}
int main(){
	freopen("a.txt","r",stdin);
	scanf("%d",&T);
	while(T--){
		int i,a,b;
		memset(first,-1,sizeof(first));
		top = 0;
		memset(d,0,sizeof(d));
		scanf("%d %d",&n,&m);
		for(i = 0;i<m;i++){
			scanf("%d %d",&a,&b);
			add(b,a);
			d[a]++;
		}
		topsort();
	}
	return 0;
}


你可能感兴趣的:(poj 3687 topsort(按顺序放球))