zoukankan      html  css  js  c++  java
  • HDU-4857(拓扑排序)

    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)拓扑排序要存储每个点的序号以及它的入度和邻边,这里为了节省空间,选择用vector<int> edge[Maxn]来存储相应序号的邻边
    (2)邻边的清空,每选出一个点,要消除所有和他相邻的边,以及相邻点的入度要-1——这一功能之所以用优先队列来实现,就是为了满足全序性。然后要重点注意一下while里面的逻辑结构,具体代码的逻辑路径根据实际问题的逻辑路径思考得来。
    (3)有一点很容易出错的地方要注意一下:就是vector容器在每次循环开始的时候必须要及时的清空,比较好的做法是尽量把该容器开到while里面去。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    #define maxn 30007
    using namespace std;
    
    int T;
    int n,m;
    int in[maxn];
    vector<int> edge[maxn];
    priority_queue<int> q;
    
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            memset(in,0,sizeof(in));
            scanf("%d%d",&n,&m);
            for(int i = 1;i <= n;i++) 
                edge[i].clear(); 
            int a,b;
            for(int j = 1;j <= m;j++) {
                scanf("%d%d",&a,&b);
                in[a]++;
                edge[b].push_back(a);
            }
            for(int i = 1;i <= n;i++)
                if(!in[i]) q.push(i);
            vector<int> ans;
            while(!q.empty()) {
                a = q.top();
                ans.push_back(a);
                q.pop();
                for(int j = 0;j < edge[a].size();j++) {
                    b = edge[a][j];
                    in[b]--;
                    if(in[b] == 0) q.push(b);
                }
            }
            for(int i = ans.size()-1;i > -1;i--) {
                if(i != 0) printf("%d ",ans[i]);
                else printf("%d
    ",ans[i]);
            }
        }
        return 0;
    }
  • 相关阅读:
    Top 10 Product Manager Skills To Boost Your Resume In 2021
    大数据知识梳理
    B端产品如何设计权限系统?
    华三盒式交换机MAC、ARP、Route性能表项参数查询
    中了传说中的挖矿病毒
    SqlServer 2019 事务日志传送
    docker中生成的pdf中文是方框的解决方案
    The Live Editor is unable to run in the current system configuration
    2021 面试题大纲
    五分钟搞定Docker安装ElasticSearch
  • 原文地址:https://www.cnblogs.com/immortal-worm/p/4943347.html
Copyright © 2011-2022 走看看