Labeling Balls
Time Limit: 1000MS
|
Memory Limit: 65536K
|
Total Submissions: 7681
|
Accepted: 2060
|
题目链接:http://poj.org/problem?id=3687
Description
Windy has
N balls of distinct weights from 1unitto Nunits. Now he tries to label them with 1 to
N in such away 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 oftest case.The first line of each test case contains two integers,
N (1 ≤ N≤ 200) and M (0 ≤ M ≤ 40,000). Thenext
Mline eachcontain two integers a and b indicating the ball labeled with
amust be lighter than the one labeledwith b. (1≤ a, b ≤
N)There is a blankline before each test case.
Output
For each test case output on a single linethe balls'weights from label 1 to label
N. If several solutions exist, youshouldoutput the one with the smallest weight for label 1, then with thesmallestweight for label 2, then with the smallest weight for label 3 and soon... Ifno 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
Source
POJFounder MonthlyContest – 2008.08.31,
windy7926778
题目大意:
输入T个测试案例,接下来输入N个点,M条边,接下来M行输入每条边的起点和终点,如果边产生回路,那么输出-1,否则按照输入的a轻于b,剩下的值就按从大到小输出。
解题思路:
将输入的n行建立有向图,如果该图产生回路,那么输出-1,如果不产生回路,将入度为0的点放进优先队列中,优先队列从大到小排序,每个队列按顺序出队,当出队的数与其他点有边存在,就在相应该点的入度减一,然后在判断是否入度为0,如果为0再次入队。本题一个比较容易出错的就是判重,如果输入两个相同的a和b,那么如果没有判重将会输出0,判重就在输入边时判断该边是否已经存在,如果存在该边的入度就不在自加。
/*
两组比较好的测试案例:
第二个测试案例有5个,但是有2个一样的,所以按4个算
2
54
51
42
13
23
105
41
81
78
41
28
ans:
24 5 3 1
逆向建图
51 6 2 7 8 3 4 9 10
没有判重边的话就输出 -1
*/
代码:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
int g[210][210];
int degree[210];//入度
int value[210];
priority_queue<int> q;//定义优先队列
//得到入度为0的点
int toposort(int n)
{
int j=n;
for(int i=1;i<=n;i++)
{
if(degree[i]==0)
{
q.push(i);
}
}
if(q.empty())
return 0;
while(!q.empty())
{
int t = q.top();
q.pop();
value[t]=j;
j--;
for(int i=1;i<=n;i++)
{
if(g[i][t]!=0)
{
g[i][t]=0;
degree[i]--;
if(degree[i]==0)
{
q.push(i);
}
}
}
}
if(j!=0)
return 0;
return 1;
}
int main()
{
int T;
int n,m;
int a,b;
scanf("%d",&T);
while(T--)
{
memset(g,0,sizeof(g));
memset(degree,0,sizeof(degree));
scanf("%d%d",&n,&m);
while(m--)
{
scanf("%d%d",&a,&b);
if(g[a][b]>0)//判重,如果输入一样的那么只算一个
degree[a]--;
g[a][b]=1;//a到b的边,起点a,终点b的边
degree[a]++;
}
int x = toposort(n);
if(x==0)
printf("-1\n");
else
{
for(int i=1;i<n;i++)
{
printf("%d ",value[i]);
}
printf("%d\n",value[n]);
}
}
return 0;
}
分享到:
相关推荐
2遍dp poj_3613解题报告 poj_3613解题报告
poj题目2775文件子目录源代码,递归经典题目,
poj典型题目解题思路详解 包含源代码和解题时应注意的问题及题目陷阱设计分析
poj 1699的代码和方法说明,个人原创
C_(POJ_1854)(分治).cpp
poj上第1990题目源码,用到了2个树状数组,这题数据结构是关键,想到了题目就很简单了
D_(POJ_1723)(思维)(sort).cpp
原理为:以数链思想,移动数组中的内容 使数组在没有扩充情况下,达成移动的效果 当然,有更简单的,大牛不要笑哦
D_(POJ_1723)(思维)(第k大数).cpp
O(nlogn)凸包问题 poj2187
POJ 3131 双向BFS解立体八数码问题
poj两道题的c++实现。已经测试过可以通过oj
问题:求平面上多个矩形的总面积。 算法:线段树(经典的线段树题目)
这是北大在线测试的第1002题,方便记忆的电话号码的解题例程,题目中有一个列表,记录着许多方便记忆的电话号码。不同的方便记忆的电话号码可能对应相同的标准号码,这个程序的任务就是找到它们
POJ题目及算法,包括动态规划、深搜广搜等算法。含相关注释。
poj 3310 的代码和方法说明,个人原创
http://poj.grids.cn/problem?id=2774 POJ 2774 木棒加工 木材厂有一些原木,现在想把这些木头切割成一些长度相同的小段木头,需要得到的小段的数目是给定了。当然,我们希望得到的小段越长越好,你的任务是计算能够...
看了测试用例后,大家估计已经明白题目的意思了吧!题目很简单,但是就是很烦。 开始直接是没思路,不知道怎么模拟,但是想了带该半个小时,就搞定了。就是把每个数存到数组里面。
POJ上面题目的解题报告。涵盖挺多的。可作参考。代码都正确。ACM新手入门必下~~ 加油...
三道几何题:hdu 1007、hdu 2289、poj 3714