HDU1285---确定比赛名次 (拓扑排序)

【题目来源】https://vjudge.net/problem/HDU-1285
【题意】
给出n个人,每人对应一个1~n的编号,如果比赛x赢y了,就在输入数据里表示为x y,问最终比赛名次是什么。
【思路】
有关于图论的排序,并且还是在拓扑排序专题题遇到,那肯定是拓扑排序啦(后者比较关键0.0),来一发裸模板,大致说一下,这个模板得来源。
假设现在有那么一个图:
这里写图片描述
说一下入度和出度的概念,入度是指一个定点通往其他点的条数,出度就是其他点到该点的条数(浅显易懂)。这个模板就是很简单的统计一下各个点的入度,每次去掉入度为0的,去掉之后,连同他所有的出度也去掉,这样一步一步,就拍完了序,按照这个图来说,就是先去掉1(为啥不去掉4呢,4也是入度为0呀,,因为题目中有说从小到大),去掉1之后,2的入度就成了0,同理可得:1 2 4 3。
【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
int ranks[500+10];
int relax[500+10][500+10],in_degree[500+10];//in_degree[]数组记录的是入度,relax数组记录的是关系。
int n,m;
void to_sort()
{
    int tot=0,k;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(in_degree[j]==0)
            {
                ranks[tot++]=j;
                in_degree[j]=-1;
                k=j;
                break;
            }
        }
        for(int j=1;j<=n;j++)
        {
            if(relax[k][j])
            {
                relax[k][j]=0;
                in_degree[j]--;
            }
        }
    }
    for(int i=0;i<tot;i++)
    {
        if(i) printf(" ");
        printf("%d",ranks[i]);
    }
    printf("\n");
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(relax,0,sizeof(relax));
        memset(in_degree,0,sizeof(in_degree));
        while(m--)
        {
            int node1,node2;
            scanf("%d%d",&node1,&node2);
            if(!relax[node1][node2])
            {
                relax[node1][node2]++;
            }
            in_degree[node2]++;
        }
        to_sort();
    }
}

当然,也可以在找谁和谁是对应的关系进而in_degree减一的时候,使用邻接表,或者因为找in_degree最小值得,所以完全可以用优先队列等等、
【代码】//邻接表

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
int ranks[500+10];
int in_degree[500+10];//in_degree[]数组记录的是入度
struct node
{
    int to,next;
}relax[2500+10];
int first[500+10];
int n,m,num;
void to_sort()
{
    int tot=0,k;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(in_degree[j]==0)
            {
                k=j;
                in_degree[k]=-1;
                break;
            }
        }
        ranks[tot++]=k;
        for(int j=first[k];j!=-1;j=relax[j].next)
        {
            in_degree[relax[j].to]--;
        }
    }
    for(int i=0;i<tot;i++)
    {
        if(i) printf(" ");
        printf("%d",ranks[i]);
    }
    printf("\n");
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(in_degree,0,sizeof(in_degree));
        for(int i=1;i<=n;i++)
        {
            first[i]=-1;
        }
        num=0;
        while(m--)
        {
            int node1,node2;
            scanf("%d%d",&node1,&node2);
            relax[num].to=node2;
            relax[num].next=first[node1];
            first[node1]=num++;
            in_degree[node2]++;
        }
        to_sort();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值