hdu 4857 逃生 拓撲 優先佇列

2021-09-12 12:53:19 字數 2542 閱讀 2247

糟糕的事情發生啦,現在大家都忙著逃命。但是逃命的通道很窄,大家只能排成一行。

現在有n個人,從1標號到n。同時有一些奇怪的約束條件,每個都形如:a必須在b之前。

同時,社會是不平等的,這些人有的窮有的富。1號最富,2號第二富,以此類推。有錢人就賄賂負責人,所以他們有一些好處。

負責人現在可以安排大家排隊的順序,由於收了好處,所以他要讓1號盡量靠前,如果此時還有多種情況,就再讓2號盡量靠前,如果還有多種情況,就讓3號盡量靠前,以此類推。

那麼你就要安排大家的順序。我們保證一定有解。

input

第一行乙個整數t(1 <= t <= 5),表示測試資料的個數。

然後對於每個測試資料,第一行有兩個整數n(1 <= n <= 30000)和m(1 <= m <= 100000),分別表示人數和約束的個數。

然後m行,每行兩個整數a和b,表示有乙個約束a號必須在b號之前。a和b必然不同。

output

對每個測試資料,輸出一行排隊的順序,用空格隔開。

sample input

15 10

3 51 4

2 51 2

3 41 4

2 31 5

3 51 2

sample output

1 2 3 4 5糟糕的事情發生啦,現在大家都忙著逃命。但是逃命的通道很窄,大家只能排成一行。

現在有n個人,從1標號到n。同時有一些奇怪的約束條件,每個都形如:a必須在b之前。

同時,社會是不平等的,這些人有的窮有的富。1號最富,2號第二富,以此類推。有錢人就賄賂負責人,所以他們有一些好處。

負責人現在可以安排大家排隊的順序,由於收了好處,所以他要讓1號盡量靠前,如果此時還有多種情況,就再讓2號盡量靠前,如果還有多種情況,就讓3號盡量靠前,以此類推。

那麼你就要安排大家的順序。我們保證一定有解。

input

第一行乙個整數t(1 <= t <= 5),表示測試資料的個數。

然後對於每個測試資料,第一行有兩個整數n(1 <= n <= 30000)和m(1 <= m <= 100000),分別表示人數和約束的個數。

然後m行,每行兩個整數a和b,表示有乙個約束a號必須在b號之前。a和b必然不同。

output

對每個測試資料,輸出一行排隊的順序,用空格隔開。

sample input

15 10

3 51 4

2 51 2

3 41 4

2 31 5

3 51 2

sample output

1 2 3 4 5

思路:明顯拓撲排序,但是要求序號最小的最先出,首先考慮一下正向建圖,發現有可能大的點會擋住小的點不能滿足最小的序號在前面

我們的目標是讓最小的點的編號盡量小

比如:1->2<-4 3

正向建圖每次讓最小的先出隊得到答案:1 4 2 3

正確答案 1 3 4 2

這並沒有讓2達到最小.

那麼需要反向建圖,相當於變成大的序號後出去,將所有能出去的點放入優先佇列,因為我們要讓前面最小的點盡量靠前,最小的點能不出隊就留下來,自然就保證了最小的點靠前

優先佇列會出去序號最大的點,那麼留下的就是序號最小的點,再反向輸出即可

#include

#define fi first

#define se second

#define for(a) for(int i=0;i#define sc(a) scanf("%d",&a)

#define show(a) cout<#define show2(a,b) cout<#define show3(a,b,c) couttypedef

long

long ll;

typedef pair<

int,

int> p;

typedef pairint> lp;

const ll inf =

1e17+10

;const

int n =

3e5+10;

const ll mod =

1000000007

;const

int base=

131;

mapint>ml;

int de[n]

,n,m,t,k,flag,top[n]

,cnt;

int co[n]

;vector<

int> v[n]

;priority_queue<

int> q;

void

bfs()}

while

(q.size()

)}}for

(int i=

1;i)printf

("%d "

,top[i]);

printf

("%d\n"

,top[n]);

}int

main()

for(

int i=

1;i<=m;i++

)bfs()

;}}

hdu 4857 逃生(優先佇列 逆拓撲排序)

題意是給你一些關係,來進行排序,前面的那個人一定在後乙個人前面,也在那些沒有交錢的人的前面。我們用逆拓撲排序,先把入度為零的數從大到小存入陣列。然後就是一般的拓撲排序。最後逆序輸出 include include include include include include includeusin...

HDU 4857 逃生 反向拓撲排序 優先佇列

hdu 4857 題意就是做乙個符合條件的排序,用到拓撲序列。我一開始wa了多發,才發現有幾個樣例過不了,發現1 2 3.的順序無法保證。後來就想用並查集強連,還是wa 後來發現髮用反向拓撲排序 優先佇列才可以通過 這裡注意把入度為0的入隊改成了出度為0的入隊 下面是ac include inclu...

HDU 4857 逃生(反向拓撲排序 優先佇列)

這題對序號輸出有要求,較小的序號優先輸出,所以用到優先佇列 優先佇列是優先彈出值最大的,所以最後要反向輸出結果,才是正確的output include include include include include include include include include using name...