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
",ans[i]);
            else
                printf("%d ",ans[i]);
        }
    }
    return 0;
}
View Code

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

#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
",j);
                    else
                        printf("%d ",j);
                    for(k=1;k<=n;k++)
                        if(sf[j][k])
                            zt[k]--;
                    break;
                }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/jasonlixuetao/p/5500608.html