Codeforces Gym 100792K King's Rout(优先队列+拓扑排序)

K. King's Rout
time limit per test
4 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

The great rout will be held this evening in the palace of his majesty Nassah II, the king of Occorom. There are n guests invited. While they are preparing evening dresses and collecting fresh rumors to talk about, the chief valet of the palace has a tricky task to solve: choose the right order for persons to arrive to the palace.

Guests always arrive one by one, that is, no two guests may arrive at the same moment of time. Due to the court etiquette, there are some limitations on the order of the arrival. For example, a notable landlord should arrive later than all his vassals, but should be earlier than his wives. After reading "Etiquette guide for dummies" the valet found out m order conditions to be satisfied. Each of them has a form: ai must come before bi. Rules are so complicated that some conditions may appear in the list two or more times.

So far the problem seems to be easy and familiar. But some guests (actually, all of them) tried to bribe valet to allow them arrive before others. So valet sorted guests according to their payoffs amounts and decided that guest number 1 should arrive as early as possible (without violating etiquette rules), among all such options valet chooses the one with the guest number 2 arriving as early as possible, and so on. All payoffs were different, so valet has no problem in selecting guests priority.

Help valet to find the best possible schedule. Guests already have numbers in valet's private list of priority, so you will not know bribes amounts and will not be accused in complicity in corruption.

Input

The first line of the input contains two integers n and m (1 ≤ n ≤ 200 0000 ≤ m ≤ 400 000) — the number of guests invited and the number of order conditions respectively.

Next m lines describe the conditions, each of them containing a single pair aibi (1 ≤ ai, bi ≤ n). That means the guest ai is required to come earlier than the guest bi.

Output

Print n different integers from 1 to n to describe the best possible order (according to valet's understanding) for guests to arrive. It is guaranteed that at least one valid order exists.

Sample test(s)
input
3 1
3 1
output
3 1 2 
input
5 6
2 1
5 2
4 1
5 4
3 1
5 3
output
5 2 3 4 1 
Note

In the first sample all the permutations where guest number 1 comes after guest number 3 are acceptable according to etiquette. As the valet wants the guest number 1 to come as early as possible he puts him on the second slot and the guest number 3 on the first slot. There is only one slot remaining for the guest number 2.


题目大意:

有编号为1~n的客人要去吃饭,然后他们会先后到达,现在已经知道了有些人一定会先于另外有些人到达,要求得到人们到达的先后次序,同时要尽量使编号小的人先到达。

思路:

通过知道了有些人先于另外某些人到达,我们可以通过拓扑排序算出他们到达的先后次序。但是题目要求编号小的人尽量先到,也就是说没有强制要求的关系里面,我们要让编号小的人先到达。

如果从头开始计算的话,我们发现情况很是复杂。比如第一个样例:3 1,即要求3在1 前面到达,如果我们按照拓扑排序的方法,会将2和3同时入队,这时候就造成了判断的难点,如果让2先出队,显然是错误的。但是我们如果反过来呢?也就是对于3 1,我们令3的入度变为1,这个时候,就是1和2同时入队,此时我们是可以分辨出谁应该先出队的。只要利用优先队列按照编号从小到大出队即可。

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
int n,m,tot;
int head[200005],indegree[200005];
struct node{
  int to,next;

}edge[400005];
  priority_queue<int>qu;
void add(int a,int b)
{
    edge[tot].to=b;
    edge[tot].next=head[a];
    head[a]=tot++;
}
void solve(int x)
{
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        int y=edge[i].to;
        indegree[y]--;
        if(!indegree[y])qu.push(y);
    }
}
int main()
{
    int i,j,k,a,b,ans[200005];

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        tot=0;
        k=0;
        while(!qu.empty())qu.pop();
        memset(indegree,0,sizeof(indegree));
        memset(head,-1,sizeof(head));
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            indegree[a]++;
            add(b,a);
        }
        for(i=1;i<=n;i++)
            if(indegree[i]==0)qu.push(i);
        while(!qu.empty())
        {
            int x=qu.top();
            ans[k++]=x;
            qu.pop();
            solve(x);
        }
        for(i=k-1;i>=0;i--)
            printf("%d ",ans[i]);  //最后倒着输出。
        printf("\n");
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值