排名 拓扑排序

排名

时间限制: 1 Sec 内存限制: 128 MB

题目描述

有 N 个比赛队(1<=N<=500),编号依次为 1,2,3……N 进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即 P1 赢 P2,用 P1,P2 表示,排名时 P1 在 P2之前。现在请你编程序确定排名。

符合条件的排名可能不是唯一的。此时要求输出时编号小的队伍在前。输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。

输入

输入有若干组。每组中的第一行为二个数N(1<=N<=500)。M;当中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中。每行也有两个整数P1。P2表示即P1队赢了P2队。

输出

给出一个符合要求的排名。输出时队伍号之间有空格。最后一名后面没有空格。

样例输入

15 20
15 4
15 11
15 5
1 4
1 8
1 2
3 2
3 13
2 5
2 9
2 6
6 5
10 13
12 9
4 7
5 12
8 7
5 8
9 10
9 11

样例输出

1 3 2 6 14 15 4 5 8 7 12 9 10 11 13

题解

拓扑排序模板题,唯一可能出现问题的地方就是题目要求同样拓扑序的两个编号小的要在前面,

这点可以通过将普通拓扑排序中的队列改为使用优先队列或者堆来实现。

直接输出结果

#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]++;//的入度++
            }
        }
        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]==1)
                {
                    degree[i]--;//相连的点的入度减1
                    if(degree[i]==0)//假设入度为0,增加队列
                        q.push(i);
                }
            }
        }
        printf("\n");
    }
    return 0;
}

 排序结果储存在vector中

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
const int maxn=510;
int graph[maxn][maxn];//保存图
int degree[maxn];//保存入度
vector<int> ans;
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);
       ans.clear();
        while(!q.empty())
        {
            int cur=q.top();
            q.pop();
            ans.push_back(cur);
            for(int i=1;i<=n;i++)
            {
                if(graph[cur][i]==1)
                {
                    degree[i]--;//相连的点的入度减1
                    if(degree[i]==0)//假设入度为0,增加队列
                        q.push(i);
                }
            }
        }
        for(int i=0;i<ans.size();i++)
        {
            printf("%d",ans[i]);
            if(i==ans.size()-1) printf("\n");
            else printf(" ");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/81253708