(POJ 3687)Labeling Balls [逆top序列] 求按照某种排列方式的字典序最小的top序列
2017-10-11 16:40
471 查看
Labeling Balls
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 14922 Accepted: 4372
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 the same label.
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
Source
POJ Founder Monthly Contest – 2008.08.31, windy7926778
题意:
有n个球,分别编号为1~n,现在设计这n个球的重量,值为1~n,并告诉m个关系 (u,v):u球的质量小于v球的质量
问你满足此条件时,依次输出球1~球n的质量?当有多种情况满足时,输出使得编号小的球质量小的情况。
分析:
首先读题之后我们就知道了是关于求top序列的问题
要使得满足“编号小的球质量小”,第一想法就是,使在队列中的度为0编号最小的球的质量成为当前最小值即可。(题目的样例也很有迷惑性)
但是,是错的。
例如下面这组数据:
1
5 4
1 4
4 2
5 3
3 2
答案应当是:
1 5 3 4 2
而按照我们之前的想法输出的是:1 5 4 2 3 所以是错误的。
为什么呢?因为在某些时刻,虽然当前编号小的质量小了,但是后面比它编号更小的质量就相对变大了,整体上是有问题的。
因此,围绕“编号小的球质量小”的条件,我们可以将它转换一下即“编号大的球质量大”。反向建边,按照top序列使得当期编号大的球质量大,在整体上就是正确的了。
AC代码:
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 14922 Accepted: 4372
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 the same label.
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
Source
POJ Founder Monthly Contest – 2008.08.31, windy7926778
题意:
有n个球,分别编号为1~n,现在设计这n个球的重量,值为1~n,并告诉m个关系 (u,v):u球的质量小于v球的质量
问你满足此条件时,依次输出球1~球n的质量?当有多种情况满足时,输出使得编号小的球质量小的情况。
分析:
首先读题之后我们就知道了是关于求top序列的问题
要使得满足“编号小的球质量小”,第一想法就是,使在队列中的度为0编号最小的球的质量成为当前最小值即可。(题目的样例也很有迷惑性)
但是,是错的。
例如下面这组数据:
1
5 4
1 4
4 2
5 3
3 2
答案应当是:
1 5 3 4 2
而按照我们之前的想法输出的是:1 5 4 2 3 所以是错误的。
为什么呢?因为在某些时刻,虽然当前编号小的质量小了,但是后面比它编号更小的质量就相对变大了,整体上是有问题的。
因此,围绕“编号小的球质量小”的条件,我们可以将它转换一下即“编号大的球质量大”。反向建边,按照top序列使得当期编号大的球质量大,在整体上就是正确的了。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <queue> using namespace std; const int maxn = 210; const int maxm = 40010; struct edge { int v,next; }edges[maxm]; int d[maxn],n,m; int head[maxn],e; int ans[maxn]; void addedges(int u,int v) { edges[e].v = v; edges[e].next = head[u]; head[u] = e++; } int main() { int t,u,v; scanf("%d",&t); while(t--) { e = 0; memset(d,0,sizeof(d)); memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d",&v,&u); //反向建边 addedges(u,v); d[v]++; } int num = n; priority_queue<int> q; for(int i=1;i<=n;i++) { if(d[i] == 0) q.push(i); } while(!q.empty()) { u = q.top(); q.pop(); ans[u] = num--; for(int i=head[u];i!=-1;i=edges[i].next) { v = edges[i].v; d[v]--; if(d[v] == 0) q.push(v); } } if(num >= 1) printf("-1\n"); else { printf("%d",ans[1]); for(int i=2;i<=n;i++) printf(" %d",ans[i]); printf("\n"); } } return 0; }
相关文章推荐
- POJ-3687-Labeling Balls-(求最小字典序拓扑序列)逆向建图-拓扑排序
- 多种排列方式满足条件,输出按照名字排列字典序最小的一个
- POJ 3687 Labeling Balls(拓扑序列)
- poj 3687 Labeling Balls 【拓扑排序 输出元素在拓扑序列中的位置】
- poj 3687 Labeling Balls【拓扑排序 输出元素在拓扑序列中的位置】
- poj 2337 欧拉回路按照最小字典序输出+注意为了按最小字典序怎么处理邻接表
- 51nod 1255 字典序最小的子序列 神奇的栈用法
- POJ 3687--Labeling Balls【拓扑排序 && 逆序拓扑 && 输出在拓扑排序中的位置】
- 【poj 3687 Labeling Balls 】(拓扑排序+优先队列,构造反向图)
- POJ 3687 Labeling Balls (逆向拓扑排序)
- (POJ 3660)Cow Contest [详解] [floyd] 传递闭包 确定top序列顺序
- POJ 3687 Labeling Balls 逆向建图,拓扑排序
- 51 nod 1255 字典序最小的子序列(单调栈 贪心)
- poj-3687-Labeling Balls
- poj 2337 Catenyms(欧拉路径的最小字典序)
- POJ训练计划3687_Labeling Balls(拓扑排序)
- poj 3687 Labeling Balls
- poj 1815 Friendship 【最小割点集】【枚举删点 + 求解最小字典序】
- POJ 3687 Labeling Balls(拓扑排序)
- 有两个序列A和B,A=(a1,a2,...,ak),B=(b1,b2,...,bk),A和B都按升序排列。对于1<=i,j<=k,求k个最小的(ai+bj)。要求算法尽量高效。