题目序号配给--CSUSTOJ1033(字典序最小的拓扑排序)

题目链接https://csustacm.fun/problem/1033

Description

在一种竞赛中,题目往往是成套出现的。一道基础题,稍加改动就会使难度上升几个档次。

现在有n道题目,编号为1~n;给出了m个二元组,每个二元组<a,b>表示 b题目是a题目的加强版,每个题目可能会有多个加强版,加强版的题目也可能会有加强版。

现在要将这n道题目放组成一场比赛,出于人文关怀方面的考虑,一道题目的简单版本必须放在其所有加强版的前面。

例如b是a的加强版,c是b的加强版 那么c在比赛中的题号必须大于a和b的题号,b的题号也必须大于a的题号

你需要做得,是输出一个长度为n的序列A,A[i] 表示编号为i的题目在比赛中的题号。

符合要求的答案很多,出题人并不想写spj,所以请输出字典序最小的方案。

Input

第一行为两个数n,m表示有n道题,m个二元组(n,m≤106)

接下来有m行,每行有两个数a,b 表示 题目b是题目a的加强版(1≤a,b≤n)。

输入保证有解

Output

按顺序输出每道题在比赛中的题号,要求字典序最小。


。。。这题也是签到题,仔细一看就差不多知道是拓扑排序了。那么我们对a必须在b前面这个条件当做引一条从a到b的有向边就可以跑拓扑排序了。注意最后输出的不是序列,而是1到n在序列中的位置。

以下是AC代码:

#include <bits/stdc++.h>
using namespace std;

const int mac=1e6+10;

int in[mac],id[mac];
vector<int>g[mac];
vector<int>ans;

int main()
{
    int n,m;
    scanf ("%d%d",&n,&m);
    for (int i=1; i<=m; i++){
        int x,y;
        scanf ("%d%d",&x,&y);
        in[y]++;
        g[x].push_back(y);
    }
    priority_queue<int,vector<int>,greater<int> >q;
    for (int i=1; i<=n; i++)
        if (in[i]==0)
            q.push(i);
    while(!q.empty()){
        int p=q.top();
        q.pop();
        ans.push_back(p);
        for (int i=0; i<g[p].size(); i++){
            int v=g[p][i];
            in[v]--;
            if (in[v]==0)
                q.push(v);
        }
    }
    for (int i=0; i<ans.size(); i++)
        id[ans[i]]=i+1;
    for (int i=1; i<n; i++)
        printf ("%d ",id[i]);
    printf ("%d\n",id[n]);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值