Labeling Balls POJ3687 【拓扑排序反向建边】【邻接表】

http://poj.org/problem?id=3687

Description

Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 to N in such a way that:

  1. No two balls share the same label.
  2. The labeling satisfies several constrains like "The ball labeled with a is lighter than the one labeled with b".

Can you help windy to find a solution?

Input

The first line of input is the number of test case. The first line of each test case contains two integers, N (1 ≤ N ≤ 200) and M (0 ≤ M ≤ 40,000). The next M line each contain two integers a and b indicating
the ball labeled with a must be lighter than the one labeled with b. (1 ≤ a, b ≤ N) There is a blank line before each test case.

Output

For each test case output on a single line the balls‘ weights from label 1 to label N. If several solutions exist, you should output the one with the smallest weight for label 1, then with the smallest weight for label 2, then with the smallest
weight for label 3 and so on... If no solution exists, output -1 instead.

Sample Input

5

4 0

4 1
1 1

4 2
1 2
2 1

4 1
2 1

4 1
3 2

Sample Output

1 2 3 4
-1
-1
2 1 3 4
1 3 2 4

If several solutions exist, you should output the one with the smallest weight for label 1, then with the smallest weight for label 2, then with the smallest weight for label 3 and so on

一开始没看懂这句话,一直WA,

如果存在这种拓扑排序,目前存在的这种序列重新编号,最轻的为1,然后是2,3,4,5……;就是说原来的排名顺序,通过这次要求排序之后时,输出他现在排第几了。然而我就直接把排完序的序列输出了,最坑的是,和所给的样例是一样的。

#include<cstdio>
#include<cstring>
#include<queue>
#define N 44000
using namespace std;
struct node
{
	int to;
	int next;
}arr[N];
int head[N];
int indegree[N];
int res[N];
int w[N];
int n;
int topo()
{
	int i,j,k;
	priority_queue<int>q;//大的先出队列
	for(j=1;j<=n;++j)
	{
		if(indegree[j]==0)
		{
			q.push(j);
		}
	}
	k=0;
	while(!q.empty())
	{
		int u=q.top();
		q.pop();
		res[k++]=u;
		for(j=head[u];j!=-1;j=arr[j].next)
		{
			int v=arr[j].to;
			indegree[v]--;
			if(indegree[v]==0)
				q.push(v);
		}
	}
	return k;
}
int main()
{
	int T,m;
	int i,j;
	int a,b;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		memset(indegree,0,sizeof(indegree));
		memset(head,-1,sizeof(head));
		for(i=1;i<=m;++i)
		{
			scanf("%d%d",&a,&b);
			arr[i].next=head[b];//反向建
			head[b]=i;
			arr[i].to=a;
			indegree[a]++;
		}
		int k=topo();
		if(k<n) printf("-1\n");
		else
		{
			for(int i=0;i<k;i++)//从重到轻重新编号
                w[res[i]]=n-i;
            printf("%d",w[1]);
            for(int i=2;i<=n;i++)
                printf(" %d",w[i]);
            puts("");
//			for(i=k-1;i>0;--i)
//				printf("%d ",res[i]);
//			printf("%d\n",res[0]);
		}
	}
	return 0;
}

/*
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

*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-18 01:13:30

Labeling Balls POJ3687 【拓扑排序反向建边】【邻接表】的相关文章

HDU2647(拓扑排序+反向建图)

题意不说了,说下思路. 给出的关系是a要求的工资要比b的工资多,由于尽可能的让老板少付钱,那么a的工资就是b的工资+1,可以确定关系为a>b,根据拓扑排序建边的原则是把"小于"关系看成有向边,那么我们可以建边v->u. #include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <algorithm> #

POJ3687 Labeling Balls (拓扑排序)经典

Labeling Balls Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11469   Accepted: 3295 Description Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 to N in such a way that: No two balls share

Labeling Balls(拓扑排序wa)

Labeling Balls Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12466   Accepted: 3576 Description Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 to N in such a way that: No two balls share

POJ 3687 Labeling Balls【拓扑排序 优先队列】

题意:给出n个人,m个轻重关系,求满足给出的轻重关系的并且满足编号小的尽量在前面的序列 因为输入的是a比b重,但是我们要找的是更轻的,所以需要逆向建图 逆向建图参看的这一篇http://blog.csdn.net/scf0920/article/details/28108243 然后用优先队列来实现的参看的这一篇 http://ycool.com/post/u9ahrwg#algo3 1 #include<iostream> 2 #include<cstdio> 3 #includ

POJ 3687 Labeling Balls 逆向拓扑排序

链接: poj3687 题意: 有N个标号为1~N的小球,重量(不包括断言)依次增加 ,现给出M句断言 ,断言格式为a b 表示小球a轻于小球b     要求根据重量大小依次输出1~N号小球应在的的位置(重量递增)不满足断言则输出-1 题解: 因为重量是依次增加的  不能按常规的构造edge[a][b]=1生成拓扑排序 既然关系格式和一般拓扑排序是相反的  我们可以尝试着构造反向边edge[b][a]=1: indegree[a]++;   再根据小球标号从后往前进行拓扑排序,即可得到一幅完整的

poj 3687 Labeling Balls 【拓扑排序】

题目链接:http://poj.org/problem?id=3687 注意重边 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include <string> #include <functional> #include <iterator> #include

poj3687拓扑排序

反向建图 #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #include &

poj3687 拓扑排序 还没怎么搞明白 回头再想想

[题意]:n个重量为1~n的球,给定一些球之间的重量比较关系(如 2 1  表示第二个球比第一个球轻),求每个球可能的重量,ans[i] 表示第i个球的重量,要求输出的是ans字典序最小的情况. [思路]:对于给出的a b  建反边,每次 在出度为0的所有点里选一个序号最小的赋值(从n开始 由大到小赋). 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string>

ACM/ICPC 之 拓扑排序-反向(POJ3687)

难点依旧是题意....需要反向构图+去重+看题 POJ3687-Labeling Balls 题意:1-N编号的球,输出满足给定约束的按原编号排列的重量序列,如果有多组答案,则输出编号最小的Ball重量最轻,若依旧多组则输出编号次小的Ball重量最轻的方案. 题解:在看懂题意后,再开始做会省很多时间...曲解题意还真是人类的本能啊. 为了完成单向关系排序,需要用到拓扑排序: 为了符合编号最小的重量最轻...的题意,需要用到反向拓扑排序: 输入可能会有重复的关系,因此需要判重: 输出需要按原编号输