poj 3687 拓扑逆排 @

Labeling Balls
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 12319   Accepted: 3534

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

Source


//输出的是各个标签的重量,


http://ycool.com/post/u9ahrwg#algo3  非常好的讲解<span id="transmark"></span>

。归纳起来就是说,对于若干条平行的路径, 小的头部不一定排在前面,但是 大的尾部一定排在后面

因为头部本身小于 尾部   而且 本题的排序方式是 先对编号小进行赋值  然后在对大的进行


  1. 6->4->1->0  原理图 
  2.  3->9->2->0 
  3.  5->7->8->0 
  4.  6 4 1 3 9 2 5 7 8 0

因为题意是先对标签1 进行尽可能小的重量的赋值    然后在对标签2 进行最小重量的赋值  然后在3

也就是在对标签1 进行赋值完之前  后面的都不能赋值 除非是 排序在  1 之前的序列

然后再对2进行


#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
//本题算法:小的头部不一定排在前面,但是 编号大的 尾部(出度为0) 一定排在后面
//所以需要逆序拓扑
int n,m;
int Map[210][210];
int du[210];      //出度
int out[210];
int TopSort()
{            
    int top;          //让重的编号尽可能大
    for(int i=n; i>=1; i--)  //决定编号
    {
        top=-1;
        for(int j=n; j>=1; j--) //决定重量
            if(!du[j])
            {
                top=j;
                break;
            }
        if(top==-1)
        {
            printf("-1\n");
            return 0;
        }
        else
        {
            du[top]=-1;
            out[top]=i;
            for(int k=1; k<=n; k++)
                if(Map[k][top])
                    du[k]--;
        }

    }
    for(int i=1; i<=n; i++)//从重到轻输出编号
    {
        if(i!=1)
            printf(" ");
        printf("%d",out[i]);
    }
    printf("\n");
}
int main()
{
    int T;
    while(~scanf("%d",&T))
    {
        while(T--)
        {
            memset(Map,0,sizeof(Map));
            memset(du,0,sizeof(du));
            scanf("%d%d",&n,&m);
            for(int i=0; i<m; i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                if(!Map[u][v])
                {
                    Map[u][v]=1;
                    du[u]++;
                }
            }
            TopSort();
        }
    }
}

/*
2
5 4
1 4
4 2
5 3
3 2

5 3
1 4
4 2
3 5
输出应该是:
1 5 3 4 2
1 3 4 2 5

http://ycool.com/post/u9ahrwg#algo3
 6->4->1->0  原理图
 3->9->2->0
 5->7->8->0
 6 4 1 3 9 2 5 7 8 0
*/


你可能感兴趣的:(poj 3687 拓扑逆排 @)