POJ 3687 Labeling Balls 逆向拓扑排序,贪心思想

题意:有n个球,他的重量从1到n个重量单位,每一个球都有自己的重量单位,并不会重复,现在给你一些顺序a b,表示a的重量比b小,让你按字典序最小找出符合所有条件的序列每一个元素表示i-th个球在序列中的位置。

想法:开始以为直接正向建边然后,top_sort从小到大找,然后输出就好了。但是这样是不对的,因为我们可以知道,如果用这种方法,得到的是球的编号的字典序输出。

5 4
5 1
4 2
1 3
2 3

就是这组数据,给你的编号是no.1<no.5,no.4<no.2......这样得到的答案是:4,2,5,1,3。这里的数字标识的还是编号no.x,而正确结果是2,4,5,3,1。

如果用贪心的思想:我们知道了位置上的数字的大小关系,那么我们找到最大的一个数,把它赋值n,在通过它找到比他小但是除它以外最大的所有的数,然后把他们中编号最大的找出,赋值n-1..........,用贪心很难找到他的确切的起点,所以倒着来。

#include<iostream>
#include<cstring>
#include<cstdio> 
#include<queue>
using namespace std;
int n,m;
int map[200+5][200+5];
int ind[200+5];
int id[200+5]; 
int ans[200+5];
struct node
{
	int x;
	friend bool operator < (node a,node b)
	{
		return a.x<b.x;
	} 
}e;
void Input()
{
	scanf("%d %d",&n,&m);
	memset(map,0,sizeof(map));
	memset(ind,0,sizeof(ind));
	for(int i=1;i<=m;i++)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		if(map[b][a]) continue;
		map[b][a]=1;
		ind[a]++;
	}
}
int top_sort()
{
	int top=n;
	priority_queue<node>q;
	while(!q.empty()) q.pop();
	for(int i=1;i<=n;i++)
	{
		if(!ind[i])
		{
			e.x=i;
			q.push(e);
		}
	} 
	while(!q.empty())
	{
		e=q.top();
		q.pop();
		ans[e.x]=top--;
		for(int i=1;i<=n;i++)
		{
			if(map[e.x][i])
			{
				if(--ind[i]==0)
				{
					node k;
					k.x=i;
					q.push(k);
				}
			}
		}
	}
	return top==0;
}
void treatment()
{
	if(!top_sort())
	{
		printf("-1\n");
		return;
	}
	for(int i=1;i<=n;i++)
	{
		printf("%d%c",ans[i],i==n?'\n':' ');
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		Input();
		treatment();
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值