(POJ 3687)Labeling Balls [逆top序列] 求按照某种排列方式的字典序最小的top序列

来源:互联网 发布:linux 下查看文件大小 编辑:程序博客网 时间:2024/06/08 22:52

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代码:

#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;}
原创粉丝点击