GYM 100792k King's Rout (拓扑排序+优先队列)

时间:2022-12-16 09:08:24

题目:

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 000, 0 ≤ 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 ai, bi (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

思路:

题目中要求对于没有强制性关系的人,要使得序号小的尽量在前边。
比如这组数据:
5 3
5 2
2 1
4 3
答案是 5 2 1 4 3
在正常的拓扑排序时没有那么多限制条件,但在这里,我们发现如果是按照每个点的入度来判断的话,比如刚才举着这个例子:
5(0)2(1)(1) // 括号里是入度
4(0)3(1)
我们可以看到在第一条链中有1,所以第一条链应该在第二条之前,但是这样的话,我们便对先放谁产生了疑问。要这么写的话,估计还得来个一场链的判断,各种复杂度就上去了。
所以我们换个思路:
5(1)2(1)(0) // 括号里是出度
4(1)3(0)
每次把出度为0的放入优先队列,每次从队列中取出最大的那个数,放在答案数组里(注意倒叙放~)。
这样就能保证每次放在后边的总是大的,即满足了强制性的关系,也把*的点中大的放在后边了。

AC代码:

#include <iostream>
#include <queue>
#include <cstdio>

using namespace std;

vector<int> dir[200010];
int deep[200010];
priority_queue<int> q;//大的优先级高
int ans[200010];

void toposort(int n){
int temp;
while(!q.empty()){
temp = q.top();
ans[n--] = temp;
q.pop();
for(int i = 0;i < dir[temp].size();i++){
deep[dir[temp][i]]--;
if(deep[dir[temp][i]] == 0) q.push(dir[temp][i]);
}
}
}

int main()
{
int n,m;
int temp1,temp2;
while(~scanf("%d%d",&n,&m)){
for(int i = 1;i <= m;i++){
scanf("%d%d",&temp1,&temp2);
dir[temp2].push_back(temp1);
deep[temp1]++;
}
for(int i = n;i >= 1;i--){
if(deep[i] == 0){
q.push(i);
}
}
toposort(n);
for(int i = 1;i <= n;i++){
printf("%d ",ans[i]);
}
printf("\n");
for(int i = 1;i <= n;i++){
dir[i].clear();
}
}
return 0;
}