演算法學習 拓撲排序

2021-10-04 07:04:51 字數 2807 閱讀 6017

相關例題

要理解拓撲排序,首先需要知道圖論的乙個基本概念:

入度:有向圖中某點作為圖中邊的終點的次數之和(某點的入邊條數)

與之相對的是出度

出度:有向圖中某點作為圖中邊的起點的次數之和(某點的出邊條數)

拿上面那張圖來說,a和b兩點的出度均為1,入度為0,而c點的入度為2

在前面已經說過,我們將每一項工作的先後順序抽象成了一條邊,只有當完成了所有的前驅工作後才能進行該工作,用圖來表示的話,就是只有當乙個結點所有的入邊都走過之後,才能訪問該結點。

那麼怎樣表示一條邊已經走過呢?我們發現,對於每個結點而言,其入邊的訪問順序是任意的,只要入邊都已經訪問過,我們就能訪問結點。因此,我們只需用乙個陣列記錄每個結點的入度,初始時從入度為0的結點開始訪問,每訪問乙個結點就將其出邊刪去(即出邊指向的結點的入度減1),那麼我們最終就能得到整個工程的完成順序。而這就是拓撲排序的過程。

由於刪去出邊**度變為0的點可能有多個,因此我們需要用佇列來儲存當前入度為0的點。

**如下:

//in[v]表示每個點的入度,圖用鏈式前向星儲存

void

topsort

(int u)

}}

這是一道簡單的拓撲排序題,只需要在原來的模板上稍加改動即可。我們用乙個權值陣列w儲存完成每項工作所需要的時間,再用乙個max陣列動態更新到每個結點時時間的最大值即可(因為工作可以同時進行,因此需要取最大值來保證該結點的前驅工作已經全部完成)

**如下:

#include

using

namespace std;

const

int maxn =

1e5+10;

struct edge

e[maxn*

100]

;struct ti

;int w[maxn]

,head[maxn]

,in[maxn]

,cnt,ans,max[maxn]

;queue q;

void

addedge

(int u,

int v,

int id)

void

read()

}void

topsort

(int u));

while

(!q.

empty()

)); ans =

max(ans,temp.t+w[v]);

}}}int

main()

我們將兩個元素之間的小於關係作為邊,將兩個元素作為點,建圖。我們發現,如果這個數列的順序是確定的,那麼每個數在其中的位置也是唯一確定的,那如何找到這個順序呢?

我們考慮每次取出這些數中的最大數,也就是入度為0的點,將這個點的所有出邊刪去,再去找剩下這些數中的最大數,即刪去出邊**度為0的點,如此迴圈下去就可以找到這些數的順序(前提是它的順序已經確定),那麼這就是乙個拓撲排序。

有了這個想法之後再去判斷其他的情況就不難了,如果我們在刪邊的過程中發現有兩個出度為0的點,那麼這個數列的順序就未被確定;如果在拓撲排序的過程中發現有環,那麼這個數列的大小關係就是矛盾的。

如何判斷有環呢?

上圖是乙個包含環的有向圖,可以發現,如果有向圖內含有環的話,拓撲排序是無法訪問到每個結點的,因為環內的每個結點的入度都無法變為0

因此我們只需要開乙個標記陣列和計數器,當拓撲排序遍歷的結點數少於當前總結點數時,就是矛盾了。

當然這道題還有不少坑點,寫的時候還是要細心些的

**如下:

#include

using

namespace std;

const

int maxn =

30,maxm =

5e5+10;

struct edge

e[maxm]

;int cnt,head[maxn]

,in[maxn]

,temp[maxn]

,n,ans[maxn]

,now;

bool vis1[maxn]

,vis2[maxn]

;queue<

int> q;

void

addedge

(int u,

int v,

int idx)

///0表示無法確定,1表示可以確定,2表示矛盾

inttopsort()

temp[i]

= in[i];}

while

(!q.

empty()

)}}if

(sum

return2;

else

if(second)

return0;

else

if(sum==n)

return1;

return0;

}int

main()

if(isok)

else

if(iscontinue)

printf

("inconsistency found after %d relations.\n"

,over)

;else

printf

("sorted sequence cannot be determined.\n");

return0;

}

演算法學習筆記(拓撲排序)

拓撲排序,在我現在看來,就是用來解決一系列分層次執行的問題。什麼意思呢?舉個例子 oi wiki上看到的 比如說我們大學生都要面臨選課問題,那麼某些課程會有一些先行課程,必須先修這些先行課程才能夠繼續修讀某課程,那麼現在問題來了,小明有n種課程需要選讀,n種課程之中,有一些課程有先後關係 也就是說修...

演算法學習 拓撲排序(佇列應用)

題目 分析 乙個節點沒有節點指向 即入度為0 的時候可以順利輸出,如果有則不能。可以用鄰接矩陣的方式來儲存現有的圖,將某節點列下所有的相加後如果等於0這說明當前結點可輸出。這裡給出關鍵 和注釋 int graph 12 12 結點數為n,用鄰接矩陣graph n n 儲存邊權 int indegre...

演算法學習筆記 19 拓撲排序

計算拓撲序列的乙個方式是,用bfs來嘗試訪問所有的節點,但是有乙個約束就是只有入度為0 00的節點才能被加入到擴充套件佇列裡。每次從佇列裡取出乙個節點,也就同時在圖中將這個節點拆除,所以它的所有後繼的節點都減少1 11,如果已經減少到0 00,那麼就可以加入到佇列中。在上面的例子中,一開始只有a a...