筆記 拓撲排序

2021-09-19 12:54:47 字數 3401 閱讀 5821

對於任何有向圖而言,其拓撲排序為其所有結點的乙個線性排序(對於同乙個有向圖而言可能存在多個這樣的結點排序)。該排序滿足這樣的條件——對於圖中的任意兩個結點u和v,若存在一條有向邊從u指向v,則在拓撲排序中u一定出現在v前面。

拓撲排序常見於判斷有向圖是否有環、統計dag的資訊等。

記錄每個節點的入度,把入度為0的節點加入佇列中。

每次從佇列中取出乙個點,把它相連的節點的入度都減一,表示刪除了這個節點。

隊列為空後,如果還有點沒有被訪問過,證明有環。

無環的情況下,節點出隊順序即是乙個拓撲序。

struct node

node[m]

;/* 返回是否有環 */

bool

topo_sort

(int n)

return cnt

}

1. hihocoder #1174 : 拓撲排序·一

給一張有向圖,判斷是否有環。

模板題

/* littlefall : hello! */

#include

using

namespace std;

using ll =

long

long

;inline

intread()

;const

int m =

100016

, mod =

1000000007

;/*topological-sort*/

struct node

node[m]

;/* 返回是否有環 */

bool

topo_sort

(int n)

return cnt

}int

main

(void

)printf

("%s\n"

,topo_sort

(n)?

"wrong"

:"correct");

}return0;

}inline

intread()

while

(ch>=

'0'&&ch<=

'9')

return x*f;

}

2. hihocoder #1175 : 拓撲排序·二

給一張有向無環圖,初始時給某些節點釋放乙個病毒。病毒會在本節點留下乙個標本,然後複製給乙個節點指向的所有子節點,並且從子節點再次重複這個過程。問整個過程結束後所有節點的病毒數量總和。

考慮拓撲排序,當乙個節點沒有入度時,就讓它開始複製,統計完它上面的病毒數後刪去這個節點即可。

/* littlefall : hello! */

#include

using

namespace std;

using ll =

long

long

;inline

intread()

;const

int m =

100016

, mod =

142857

;struct node

node[m]

;int

topo_sort

(int n)

int ans =0;

while

(!q.

empty()

)}return ans;

}int

main

(void

)int ans =

topo_sort

(n);

printf

("%d\n"

,ans )

;return0;

}inline

intread()

while

(ch>=

'0'&&ch<=

'9')

return x*f;

}

3. hdu 4857

現在有n個人需要排序,給定一些要求(i,

j)(i,j)

(i,j

),表示i

ii必須在j

jj的前面。在滿足這些條件的同時,需要讓1號盡量往前,再讓2號盡量往前,依次類推。資料保證有解。

注意這個順序並非字典序最小,比如對於以下dag:

字典序最小的排序是:3 5 6 4 1 7 8 9 2

題目要求排序是: 6 4 1 3 9 2 5 7 8,因為要讓1所在位置最靠前。

正確的做法是建立乙個反圖,並且求字典序最大的拓撲序。

/* littlefall : hello! */

#include

using

namespace std;

using ll =

long

long

;inline

intread()

;const

int m =

30016

, mod =

1000000007

;struct node

node[m]

;vector<

int>

topo_sort

(int n)

vector<

int> res;

while

(!pq.

empty()

)}return res;

}int

main

(void

) vector<

int> ord =

topo_sort

(n);

reverse

(ord.

begin()

, ord.

end())

;for

(int i=

0;i<

(int

)ord.

size()

;++i)

printf

("%d%c"

,ord[i]

," \n"

[i==

(int

)ord.

size()

-1])

;}return0;

}inline

intread()

while

(ch>=

'0'&&ch<=

'9')

return x*f;

}

拓撲排序入門(真的很簡單)_獨-的csdn客

拓撲排序筆記

具體的實現 1 找到乙個入度為零的點,把它丟進佇列。2 把這個點以及與這個點相連的邊都刪去。3 重複1 2直到圖為空。對,又有個裸題 poj 2367 genealogical tree鏈結 就是直接把拓撲排序後的序列輸出即可。如下 include include include include u...

拓撲排序學習筆記

1.拓撲排序只對於有向無環圖而言 directed acyclic graph簡稱dag 2.在乙個有向無環圖中,若a b c,則拓撲序列為 a,b,c 也就是說如果一條邊a b,那麼在拓撲序列裡a就在b前面 知道了這兩點,那麼就可以來求拓撲序列了 首先,我們知道在dag中一定存在乙個入度為0的點,...

拓撲排序學習筆記

1.輸出字典序最小的拓撲序 在bfs演算法方法中用優先佇列 2.題意 n個點m條邊 dag 求刪去每個點後1 n最短路 n,m 3e5 做法 首先在dag中可以跑拓撲排序,跑完拓撲排序有什麼好處呢?拓撲序上的乙個點k作為劃分線,前半段的點的集合設為x,後半段點的集合設為y,那麼從點1到x中的任意乙個...