您的位置:首页 > 其它

Poj 3687 Labeling Balls (拓扑排序)

2014-02-27 16:07 357 查看
题意:n个重量为1~n的球,给定一些编号间的重量比较关系,现在给每个球编号,在符合条件的前提下使得编号小的球重量小。(先保证1号球最轻,其次2号……)
思路:拓扑排序,反向建图。利用优先队列保证每次被处理点的编号最小。
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int N=205;

struct Node
{
	int id,degree; //初始编号 入度
	bool operator < (const Node &a) const
	{
		return id<a.id;
	}
}data
;

int n,m,cnt;
bool graph

,vis
;
int ans
,s
;

bool Deal ()
{
	priority_queue <Node> q;
	int i;
	for (i=1;i<=n;i++) //所有入度为0的点先入队
		if (data[i].degree==0)
			q.push(data[i]);

	while (!q.empty())
	{
		Node cur=q.top();
		q.pop();
		if (cur.degree==0 && vis[cur.id]==false)
		{
			s[cnt++]=cur.id;  //记录处理顺序
			vis[cur.id]=true;
			for (i=1;i<=n;i++)
				if (vis[ data[i].id ]==false)
				{
					if (graph[cur.id][data[i].id])
						data[i].degree--;
					if (data[i].degree==0)
						q.push(data[i]);
				}
		}
	}
	if (cnt<=n) return true; //有环
	return false;
}

int main ()
{
	int T,i;
	scanf("%d",&T);
	while (T--)
	{
		scanf("%d%d",&n,&m);
		for (i=1;i<=n;i++)
			data[i].id=i,data[i].degree=0;
		cnt=1;
		
		memset(graph,false,sizeof(graph));
		memset(vis,false,sizeof(vis));
		memset(ans,0,sizeof(ans));
		memset(s,0,sizeof(s));
		while (m--)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			if (graph[b][a]==false)
			{//处理重边,避免影响入度
				graph[b][a]=true;
				data[a].degree++;
			}
		}
		if (Deal())
			printf("-1\n");
		else
		{
			for (i=1;i<cnt;i++)
				ans[ s[cnt-i] ] = i;
			for (i=1;i<=n;i++)
				printf(i==n?"%d\n":"%d ",ans[i]);
		}
	}
	return 0;
}

/*
测试数据转自 http://poj.org/showmessage?message_id=145313 2

5 4
5 1
4 2
1 3
2 3

10 5
4 1
8 1
7 8
4 1
2 8
ans:
2 4 5 3 1        逆向建图
5 1 6 2 7 8 3 4 9 10  没有判重边的话就输出 -1
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: