HDU_1285_拓扑排序(优先队列)

确定比赛名次

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

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

在数据结构中学了拓扑排序后,再做了一次,本想用栈实现,结果wa哭了,然后发现,题目要求有多种情况时尽量由小到大排出,用栈没有办法实现(可能是可以实现的),用优先队列相当方便。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

int map[505][505];
int degree[505],ans[505];
int n,m;

struct cmp1{
    bool operator ()(int &a,int &b){
        return a>b;//最小值优先
    }
};

/*bool operator<(const int &a,const int &b)
{
    if(a<b)
        return 1;
    return 0;
}*/

void topusort()
{
    priority_queue<int,vector<int>,cmp1> s;
    while(!s.empty())
        s.pop();
    int cnt=0;
    for(int i=n; i>=1; i--)
    {
        if(degree[i]==0)
        {
            s.push(i);
        }
    }
    while(!s.empty())
    {
        int h=s.top();
        s.pop();
        degree[h]--;
        ans[cnt++]=h;
        for(int i=n; i>=1; i--)
        {
            if(map[h][i]==1)
            {
                //map[h][i]=0;
                degree[i]--;
                if(degree[i]==0)
                    s.push(i);
            }
        }
    }
}
int main()
{

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(map,0,sizeof(map));
        memset(degree,0,sizeof(degree));
        memset(ans,0,sizeof(ans));
        for(int i=0; i<m; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(map[x][y]==0)
            {
                map[x][y]=1;
                degree[y]+=1;
            }
        }
        //cout<<degree[3]<<endl;
        topusort();
        for(int i=0;i<n;i++)
        {
            if(i==n-1)
                printf("%d\n",ans[i]);
            else
                printf("%d ",ans[i]);
        }
    }
    return 0;
}

再附上第一次做时模拟的代码:

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
int sf[510][510],zt[510];
int main()
{
    int n,m,p1,p2;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(sf,0,sizeof(sf));
        memset(zt,0,sizeof(zt));
        while(m--)
        {
            scanf("%d%d",&p1,&p2);
            if(!sf[p1][p2])
            {
                sf[p1][p2]=1;
                zt[p2]++;
            }
        }
        int i,j,k;
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
                if(zt[j]==0)
                {
                    zt[j]--;
                    if(i==n)
                        printf("%d\n",j);
                    else
                        printf("%d ",j);
                    for(k=1;k<=n;k++)
                        if(sf[j][k])
                            zt[k]--;
                    break;
                }
    }
    return 0;
}

时间: 2024-10-10 21:06:19

HDU_1285_拓扑排序(优先队列)的相关文章

hdu--1285 &amp;&amp; 4857 --正向 || 逆向拓扑排序 &amp;&amp; 优先队列

头太晕了 喝了太多 .. 就想提一点 对于 拓扑排序的这2题 为什么一个是正向 一个是逆向 主要是看题目要求  因为拓扑排序的结果总是有很多种存在的 一般来说 它会让你输出它指定要求的形式的答案 那么 如果是按字典序输出 就是 greater<int> 情况下的优先队列 并且 正向 如果是尽量使小的数字 靠前输出 而不是追求 字典序 可以考虑 逆向拓扑 逆向输出 但 这些都不是唯一的 一定要分析好题目 曾经 看过一个讲动态规划的word  说拓扑是为DP作准备的 似乎有点道理 这两题 代码 实

hdu4857 逃生 反拓扑排序+优先队列, 靠前的数字的优先输出.

逃生 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 734    Accepted Submission(s): 199 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前. 同时,社会是

hdoj 4857 逃生(逆向拓扑排序+优先队列)

逃生 点击打开链接 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2161    Accepted Submission(s): 608 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前

HDU 1285 确定比赛名次(拓扑排序+优先队列)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1285 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前.现在请你编程序确定排名. Input 输入有若干组,每组中的第一行为二个数N(1<=N<

HDU 4857 (反向拓扑排序 + 优先队列)

题意:有N个人,M个优先级a,b表示a优先于b,并且每个人有个编号的优先级,输出顺序. 思路来自:与PKU3687一样 在基本的拓扑排序的基础上又增加了一个要求:编号最小的节点要尽量排在前面:在满足上一个条件的基础上,编号第二小的节点要尽量排在前面:在满足前两个条件的基础上,编号第三小的节点要尽量排在前面--依此类推.(注意,这和字典序是两回事,不可以混淆.) 如图 1 所示,满足要求的拓扑序应该是:6 4 1 3 9 2 5 7 8 0. 图 1 一个拓扑排序的例子 一般来说,在一个有向无环图

HDU 4857 拓扑排序 优先队列

n个数,已经有大小关系,现给m个约束,规定a在b之前,剩下的数要尽可能往前移.输出序列 大小关系显然使用拓扑结构,关键在于n个数本身就有大小关系,那么考虑反向建图,优先选择值最大的入度为零的点,这样得到的序列就是从大到小的,最后倒序输出就行了. 写这题的时候头好痛阿肚子好痛阿,再也不想熬夜了,一点效率都没有. /** @Date : 2017-09-29 19:29:12 * @FileName: HDU 4857 拓扑排序 + 优先队列.cpp * @Platform: Windows * @

hdu 4857 逃生 拓扑排序+优先队列,逆向处理

hdu4857 逃生 题目是求拓扑排序,但不是按照字典序最小输出,而是要使较小的数排在最前面. 一开始的错误思路:给每个点确定一个优先级(该点所能到达的最小的点),然后用拓扑排序+优先对列正向处理,正向输出.这是错误的,如下样例: 1 5 4 5 2 4 3 2 1 3 1 正确的解法:是反向建边,点大的优先级高,用拓扑排序+优先队列,逆向输出序列即可. 根据每对限制,可确定拓扑序列,但此时的拓扑序列可能有多个(没有之间关系的点的顺序不定).本题要求较小的点排到前面,则可确定序列. (1)如果点

HDU 5638 拓扑排序+优先队列

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5638 题意: 给你一个DAG图,删除k条边,使得能个得到字典序尽可能小的拓扑排序 题解: 把拓扑排序的算法稍微改一下,如果某个顶点的入度小于k也把它加到优先队列里面去. k减小后队列里面会有些点不满足<=k,直接踢出来就好了. 代码: #include<iostream> #include<cstring> #include<cstdio> #include<

POJ 3687 Labeling Balls【拓扑排序 优先队列】

题意:给出n个人,m个轻重关系,求满足给出的轻重关系的并且满足编号小的尽量在前面的序列 因为输入的是a比b重,但是我们要找的是更轻的,所以需要逆向建图 逆向建图参看的这一篇http://blog.csdn.net/scf0920/article/details/28108243 然后用优先队列来实现的参看的这一篇 http://ycool.com/post/u9ahrwg#algo3 1 #include<iostream> 2 #include<cstdio> 3 #includ