zoukankan      html  css  js  c++  java
  • HDU 4857 逃生 拓扑排序好题 第一次做CLJ出的题

              逃生



    Problem Description
    糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。

    现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。
    同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。

    负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。

    那么你就要安排大家的顺序。我们保证一定有解。
     
    Input
    第一行一个整数T(1 <= T <= 5),表示测试数据的个数。
    然后对于每个测试数据,第一行有两个整数n(1 <= n <= 30000)和m(1 <= m <= 100000),分别表示人数和约束的个数。

    然后m行,每行两个整数a和b,表示有一个约束a号必须在b号之前。a和b必然不同。
     
    Output
    对每个测试数据,输出一行排队的顺序,用空格隔开。
     
    Sample Input
    1
    5 10
    3 5
    1 4
    2 5
    1 2
    3 4
    1 4
    2 3
    1 5
    3 5
    1 2
     
    Sample Output
    1 2 3 4 5
     
     
     
     
    这道题刚开始理解错题意了,这道题不是保证字典序,而是要最小的数字尽量在前面。
    比如要1在不矛盾的情况下尽量在前面,然后2尽量在前面......
     
    我刚开始:
    要最小的尽量在前面,那就用priority_queue,然后从小到大,拓扑排序
    但是这样只能保证拿出来的数字在当前队列中是最小的,而不能保证最后最小的一定在尽量前的位置。
    比如:
    较小,较大,最小,然后较大有连接最小的边,这样我输出是:较小,较大,最小,
    但更优的情况是:较大,最小,较小
    因为这样最小在更前的位置了。
     
    那怎么做呢?
    我是看了题解才知道的:
    优先级:大到小的priority_queue
    逆向建图+反向输出结果
     
     
    为什么呢?
    要最小的尽量前,我们就把最小的尽量放在后面,则priority_queue的优先级:从大到小,然后反向输出,
    但是反向输出后的序列又要满足拓扑排序的规律,所以我们先要逆向建图。
    这样反向输出后不就相当于正向了吗?
     
    通过这道题自己也是学习了好多。
     
     
     
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<vector>
     6 
     7 using namespace std;
     8 
     9 const int maxn=30000+5;
    10 
    11 int f[maxn];
    12 int inde[maxn];
    13 vector<int>edge[maxn];
    14 int tot;
    15 
    16 void solve(int n)
    17 {
    18     tot=1;
    19 
    20     priority_queue<int>que;
    21     while(!que.empty())
    22         que.pop();
    23 
    24     for(int i=1;i<=n;i++)
    25     {
    26         if(inde[i]==0)
    27             que.push(i);
    28     }
    29 
    30     while(!que.empty())
    31     {
    32         int u=que.top();
    33         f[tot++]=u;
    34         que.pop();
    35 
    36         for(int i=0;i<edge[u].size();i++)
    37         {
    38             int v=edge[u][i];
    39             inde[v]--;
    40             if(inde[v]==0)
    41                 que.push(v);
    42         }
    43     }
    44 
    45     for(int i=tot-1;i>1;i--)
    46         printf("%d ",f[i]);
    47     printf("%d
    ",f[1]);
    48 
    49     return ;
    50 }
    51 
    52 int main()
    53 {
    54     int test;
    55     scanf("%d",&test);
    56 
    57     while(test--)
    58     {
    59         int n,m;
    60         scanf("%d%d",&n,&m);
    61 
    62         memset(inde,0,sizeof(inde));
    63         for(int i=1;i<=n;i++)
    64             edge[i].clear();
    65 
    66         int u,v;
    67         for(int i=1;i<=m;i++)
    68         {
    69             scanf("%d%d",&u,&v);
    70             edge[v].push_back(u);
    71             inde[u]++;
    72         }
    73 
    74         solve(n);
    75     }
    76 
    77     return 0;
    78 }
    343ms
     
     
     
     
     
     
     

     

  • 相关阅读:
    #1045
    PHP程序员的技术成长规划
    403 Forbidden
    读《暗时间》的思考
    常用判断重复记录的SQL语句
    PHP中生产不重复随机数的方法
    echo 1+2+"3+4+5“输出的结果是6
    GET vs. POST
    详解PHP中的过滤器(Filter)
    Session变量在PHP中的使用
  • 原文地址:https://www.cnblogs.com/-maybe/p/4492213.html
Copyright © 2011-2022 走看看