• [ACM] hdu 1285 确定比赛名次 (拓扑排序)


    确定比赛名次

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 10358    Accepted Submission(s): 4046


    Problem Description
    有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
     
    Input
    输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
     
    Output
    给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。

    其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
     
    Sample Input
    4 3 1 2 2 3 4 3
     
    Sample Output
    1 2 4 3
     
    Author
    SmallBeer(CML)
     
    Source

    我对拓扑排序的理解:根据自定义值的大小排序(大数的不一定大,小数不一定小)。自定义谁在前谁在后。

    解题思路:

    原理:拓扑排序是应用于有向无回路图(DAG)上的一种排序方式,对一个有向无回路进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u在v的前面。该序列说明了顶点表示的事件或 状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时可以以工程为顶点,工程间的依赖关系为边建立图,用拓扑排序来求得所有工程的合理执行顺序。

    对一个DAG进行拓扑排序有两种方法,广度优先搜索和深度优先搜索。

    这里介绍广度优先搜索,进行拓扑排序时,每次可以拿出的顶点一定是入度为0的点,即没有被指向的点,因为这样的点表示的事件没有依赖,在一个入度为0的点表示的事件执行完之后,它所指向的顶点所依赖的点就少了一个,所以我们可以先将所有入度为0的点加入一个队列中,然后依次将它们所指向的点的入度减1,再将入度变为0的点也依次加入队列中,这样最后就可以得到一个拓扑有序的序列。

    本题中说符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前,需要用到优先队列,每次从队列中取的是最小的那个元素。

    代码:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    const int maxn=510;
    int graph[maxn][maxn];//保存图
    int degree[maxn];//保存入度
    
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(graph,0,sizeof(graph));
            memset(degree,0,sizeof(degree));
            for(int i=0;i<m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                if(!graph[u][v])
                {
                    graph[u][v]=1;
                    degree[v]++;//v的入度++
                }
            }
            priority_queue<int,vector<int>,greater<int> >q;
            for(int i=1;i<=n;i++)
                if(degree[i]==0)
                q.push(i);
            bool first=1;
            while(!q.empty())
            {
                int cur=q.top();
                q.pop();
                if(first)
                {
                    cout<<cur;
                    first=0;
                }
                else
                    cout<<" "<<cur;
                for(int i=1;i<=n;i++)
                {
                    if(graph[cur][i])
                    {
                        degree[i]--;//相连的点的入度减1
                        if(degree[i]==0)//如果入度为0,加入队列
                            q.push(i);
                    }
                }
            }
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    c语言 inline函数
    ubuntu18.04 安装新版本openssl
    convert_mnist_data.cpp
    caffe 安装方法和记录
    【转】jdbc:oracle:thin:@localhost:1521:orcl与jdbc:oracle:thin:@//localhost:1521/orcl区别
    【原创】【HCIA】验证GaussDB 100系统函数to_nchar()是否能支持最大字节长度8000
    【原创】达梦数据库DM7备份与恢复
    【LINUX】操作系统时钟与硬件时钟设置
    【文档】ORACLE RAC 修改SCAN监听端口、VIP网络配置参考文档
    【转】11G R2 RAC: HOW TO IDENTIFY THE MASTER NODE IN RAC
  • 原文地址:https://www.cnblogs.com/yzm10/p/7229672.html
Copyright © 2020-2023  润新知