zoukankan      html  css  js  c++  java
  • poj3687拓扑排序

    Labeling Balls
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 14749   Accepted: 4325

    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, 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 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
    这题要反向。个人理解如下

    如果正向的话,也就是说从1到n第一个入度为0的就赋予最小值,但倘若如下情况有2比4轻,3比1轻,那么如果按照正向算法,显然最后答案是4,1,2,3;但若是先赋予3的话有2,3,1,4.显然后者是最优解。
    这个问题实质上就是交换,用2较小交换1较小,这个交换显然是可以的,也就是说正向的话可能会存在一些问题。
    而若是反向的话,也就是说从n到1第一个出度为0的就赋予最大值,可以简单想一下,第一步肯定是正确的,因为肯定是将编号大的赋予较大值,而第二步会不会存在交换的问题呢?显然是不存在的,因为我们
    可以由正向的知道,所谓交换就是拿序号大的较大交换序号小的较大,显然就出现问题了,所以无法进行类似正向的交换。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=208;
    bool mp[N][N];
    int in[N],ans[N];
    int main()
    {
        int T,n,m;
        for(scanf("%d",&T); T--;)
        {
            scanf("%d%d",&n,&m);
            memset(mp,0,sizeof(mp));
            memset(in,0,sizeof(in));
            int a,b;
            while(m--)
            {
                scanf("%d%d",&a,&b);
                if(!mp[b][a]) ++in[a];
                 mp[b][a]=1;
            }
            bool ok=1;
            int k=n,i;
            while(k>=1)
            {
                for(i=n; i>=1; --i)
                {
                    if(in[i]==0)
                    {
                        --in[i];
                        ans[i]=k--;
                        for(int j=1; j<=n; ++j)
                            if(mp[i][j]) --in[j];
                        break;
                    }
                }
                if(i==0)
                {
                    ok=0;
                    break;
                }
            }
            if(ok)
            {
                for(int i=1; i<=n; ++i) printf("%d ",ans[i]);
                puts("");
            }
            else puts("-1");
        }
    }
  • 相关阅读:
    【HDOJ】4982 Goffi and Squary Partition
    【HDOJ】4983 Goffi and GCD
    【算法导论】学习笔记——第7章 快速排序
    【算法导论】学习笔记——第6章 堆排序
    【HDOJ】4956 Poor Hanamichi
    【HDOJ】2492 Ping pong
    【Linux】鸟哥的Linux私房菜基础学习篇整理(十二)
    【Linux】鸟哥的Linux私房菜基础学习篇整理(十一)
    统计硬币
    放大的X
  • 原文地址:https://www.cnblogs.com/mfys/p/7284145.html
Copyright © 2011-2022 走看看