P1347 排序(拓撲排序)

2021-10-09 05:23:35 字數 1866 閱讀 5323

題目傳送門

這題雖然是一道藍題,但他的資料很小,所以,我們可以每輸入乙個關係就拓撲一次

我們可以把結果分為三種情況

這裡我們可以用拓撲把度清零,記錄每個字母都出現過

並且判斷最長的鏈是多少就行了

f[a[i].to]=max(f[a[i].to],f[p[h]]+1);//找最長鏈 s=max(s,f[a[i].to]);

如果最長鏈小於n,那麼就沒有得到整體關係

提問

那麼就有人問了,為什麼得不到呢,難道不是經過拓撲後都為0,並且n個字母都出現過就行了嗎?

回答

我們拿個樣例來講

4 6c1.c→d

2.c→d↘b

3.c→d

↘b→a

當我們執行到第三步時,所有字母都出現過,並且經過拓撲排序,所有度都會為0

,但是答案卻錯了,因為d與b之間沒有大小關係,最長鏈為c所以,要判斷最長鏈是否等於n接下來,就是輸出的問題

我們可以建鄰接表,最小的為根,最大的為葉

這樣,最先出隊(也就是度為0)的字母就是最小的字母

if

(s==n)

//判斷最長鏈是否為n,第一種情況

這裡,處理就很簡單了,只要判斷拓撲排序後,度是否還是大於0,實際就是判斷有沒有出現環

ok=1;

for(

int j=

0;j)//判斷是否有環

if(b[j]

>0)

這裡就更簡單,如果1和2都沒有成立,那麼就是第3個條件

還要有個特判

那剛剛的樣例講

4 6cif

(x==y)

//特判

下面呈上ac**

#include

using

namespace std;

char ch;

int n,m,x,y,h,t,s,ok,tot,b[30]

,c[30

],p[30]

,o[30

],f[30]

,du[30]

,head[30]

;struct node

a[1005];

void

add(

int x,

int y)

//鄰接表

; head[x]

=tot;

}voidtp(

)//拓撲排序

while

(h}int

main()

add(x,y)

;//建圖

du[y]++;

//度++tp(

);//拓撲

ok=1;

for(

int j=

0;j)//判斷是否有環

if(b[j]

>0)

if(ok==0)

//第2種情況

if(s==n)

//判斷最長鏈是否為n,第1種情況

} cout<<

"sorted sequence cannot be determined."

;//如果前2種情況都不是,就是第3種

return0;

}

洛谷 P1347 排序 拓撲排序

題目 乙個不同的值的公升序排序數列指的是乙個從左到右元素依次增大的序列,例如,乙個有序的數列a,b,c,d 表示a第一行有兩個整數n,m,n表示需要排序的元素數量,2 n 26,第1到n個元素將用大寫的a,b,c,d 表示。m表示將給出的形如a接下來有m行,每行有3個字元,分別為乙個大寫字母,乙個 ...

洛谷 P1347 排序 拓撲排序

乙個不同的值的公升序排序數列指的是乙個從左到右元素依次增大的序列,例如,乙個有序的數列 a,b,c,da,b,c,da,b,c,d 表示a abc d。在這道題中,我們將給你一系列形如 a a b 的關係,並要求你判斷是否能夠根據這些關係確定這個數列的順序。第一行有兩個正整數 n,mn,mn,m,n...

洛谷P1347 排序

這個題看到很多人寫topo排序,其實這道題第一眼看更像是乙個差分約束的裸題qwq.令dis x 表示x的相對大小 1是最小,n是最大 顯然,對於乙個關係a 而我們最後要求的就是dis x 的最小值,為了使它們的值都落在1 n之間,我們新建乙個虛擬的點0,並令dis 0 0且dis x dis 0 這...