POJ 3687 Labeling Balls(拓扑排序+反向思考)

Labeling Balls
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 13776   Accepted: 3983

Description

Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 toN 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 withb".

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 nextM line each contain two integers a and b indicating the ball labeled witha must be lighter than the one labeled with b. (1 ≤ a, bN) 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 labelN. 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组大小关系,a b表示标号为a的盒子放的球比标号为b的盒子放的球轻。从左到右输出每个盒子里的球的重量,而且前面的盒子里的球要尽可能的小。(注意是按照盒子的顺序输入里面的球,不是输出各个球所在的盒子!!!不知道自己WA哪的同学好好读一下题)

解题思路:
    这题确实题意杀,思维有点绕,开始读错题了WA了好几发。
    我们每个盒子之间的约束条件,如果直接拓扑排序得到的是怎么摆放盒子,使它们内部的球为1~N,然而这并不是题目问的。
    由于要求字典序最小,我们要让第一个盒子装尽可能轻的球,然而根据题目条件给盒子找球并不好实现。所以我们可以从相反的角度思考一下:我们只要让重的球尽可能放在后面就可以保证字典序最小,这样就转化成了给球找盒子,直接贪心地拓扑排序即可。

AC代码:
#include 
#include 
#include 
#include 
#include 
using namespace std;

const int maxn=200+3;
int N,M;
bool used[maxn];//是否每个盒子是否已经放球的
vector G[maxn];//入边表
int out[maxn],ans[maxn];

bool toposort()
{
    for(int i=N;i>0;--i)//先分配重的球
    {
        int select=-1;
        for(int j=N;j>0;--j)//优先放右边的盒子
            if(!used[j]&&!out[j])
            {
                select=j;
                break;
            }
        if(select==-1)//存在环,无解
            return false;
        for(int j=0;j


你可能感兴趣的:(POJ,算法,图论)