【圖論】有向無環圖的拓撲排序
1. 引言
有向無環圖(Directed Acyclic Graph, DAG)是有向圖的一種,字面意思的理解就是圖中沒有環。常常被用來表示事件之間的驅動依賴關係,管理任務之間的排程。拓撲排序是對DAG的頂點進行排序,使得對每一條有向邊(u, v),均有u(在排序記錄中)比v先出現。亦可理解為對某點v而言,只有當v的所有源點均出現了,v才能出現。
下圖給出有向無環圖的拓撲排序:
下圖給出的頂點排序不是拓撲排序,因為頂點D
的鄰接點E
比其先出現:
2. 演算法原理與實現
拓撲排序的實現演算法有兩種:入度表、DFS,其時間複雜度均為\(O(V+E)\)。
入度表
對於DAG的拓撲排序,顯而易見的辦法:
- 找出圖中0入度的頂點;
- 依次在圖中刪除這些頂點,刪除後再找出0入度的頂點;
- 然後再刪除……再找出……
- 直至刪除所有頂點,即完成拓撲排序
為了儲存0入度的頂點,我們採用資料結構棧
(亦可用佇列);演算法的視覺化可參看這裡。
圖用鄰接表(adjacency list)表示,用陣列inDegreeArray[]
記錄結點的入度變化情況。C實現:
// get in-degree array int *getInDegree(Graph *g) { int *inDegreeArray = (int *) malloc(g->V * sizeof(int)); memset(inDegreeArray, 0, g->V * sizeof(int)); int i; AdjListNode *pCrawl; for(i = 0; i < g->V; i++) { pCrawl = g->array[i].head; while(pCrawl) { inDegreeArray[pCrawl->dest]++; pCrawl = pCrawl->next; } } return inDegreeArray; } // topological sort function void topologicalSort(Graph *g) { int *inDegreeArray = getInDegree(g); Stack *zeroInDegree = initStack(); int i; for(i = 0; i < g->V; i++) { if(inDegreeArray[i] == 0) push(i, zeroInDegree); } printf("topological sorted order\n"); AdjListNode *pCrawl; while(!isEmpty(zeroInDegree)) { i = pop(zeroInDegree); printf("vertex %d\n", i); pCrawl = g->array[i].head; while(pCrawl) { inDegreeArray[pCrawl->dest]--; if(inDegreeArray[pCrawl->dest] == 0) push(pCrawl->dest, zeroInDegree); pCrawl = pCrawl->next; } } }
時間複雜度:得到inDegreeArray[]
陣列的複雜度為\(O(V+E)\);頂點進棧出棧,其複雜度為\(O(V)\);刪除頂點後將鄰接點的入度減1,其複雜度為\(O(E)\);整個演算法的複雜度為\(O(V+E)\)。
DFS
在DFS中,依次列印所遍歷到的頂點;而在拓撲排序時,頂點必須比其鄰接點先出現。在下圖中,頂點5
比頂點0
先出現,頂點4
比頂點1
先出現。
在DFS實現拓撲排序時,用棧來儲存拓撲排序的頂點序列;並且保證在某頂點入棧前,其所有鄰接點已入棧。DFS版拓撲排序的視覺化參看這裡。
C實現:
/* recursive DFS function to traverse the graph, * the graph is represented by adjacency list */ void dfs(int u, Graph *g, int *visit, Stack *s) { visit[u] = 1; AdjListNode *pCrawl = g->array[u].head; while(pCrawl) { if(!visit[pCrawl->dest]) dfs(pCrawl->dest, g, visit, s); pCrawl = pCrawl->next; } push(u, s); } // the topological sort function void topologicalSort(Graph *g) { int *visit = (int *) malloc(g->V * sizeof(int)); memset(visit, 0, g->V * sizeof(int)); Stack *s = initStack(); int i; for(i = 0; i < g->V; i++) { if(!visit[i]) dfs(i, g, visit, s); } // the order of stack element is the sorted order while(!isEmpty(s)) { printf("vertex %d\n", pop(s)); } }
時間複雜度:應與DFS相同,為\(O(V+E)\)。
3. 參考資料
相關推薦
【圖論】有向無環圖的拓撲排序
1. 引言 有向無環圖(Directed Acyclic Graph, DAG)是有向圖的一種,字面意思的理解就是圖中沒有環。常常被用來表示事件之間的驅動依賴關係,管理任務之間的排程。拓撲排序是對DAG的頂點進行排序,使得對每一條有向邊(u, v),均有u(在排序記錄中)比v先出現。亦可理解為對某點v而言,只
【bzoj1143: [CTSC2008]祭祀river】有向無環圖的最長反鏈
1143: [CTSC2008]祭祀river Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3192 Solved: 1632 [Submit][Status][Discuss] Description 在遙遠
HDU 3249 Test for job (有向無環圖上的最長路,DP)
code head struct sin == cout article scanf for ?? 解題思路: 求有向無環圖上的最長路。簡單的動態規劃#include <iostream> #include <cstring> #include
HOJ 13845 Atomic Computer有向無環圖的動態規劃
-1 會有 bsp pre 但是 自帶 += 排列組合 開始 考慮任意一個數字,任何一個都會有奇怪的。。性質,就是一個可以保證不重復的方案——直接簡單粗暴的最高位加數字。。於是,如同上面的那個題:+1、-1、0 但是考慮到65536KB的標準內存限制,會得出一個奇怪的性質,
CSU 1804 - 有向無環圖 - [樹形DP]
其中 如果 init max 枚舉 time 包含 mod %d 題目鏈接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 Bobo 有一個 n 個點,m 條邊的有向無環圖(即對於任意點 v,不存在從點 v 開
c/c++ 有向無環圖 directed acycline graph
rect 如果 拓撲排序 type 第一個 ima 結構 alt lse c/c++ 有向無環圖 directed acycline graph 概念: 圖中點與點之間的線是有方向的,圖中不存在環。用鄰接表的方式,實現的圖。 名詞: 頂點的入度:到這個頂點的線的數量。 頂
狄克斯拉特算法。 適用於,加權有向無環圖,且無負權邊,的最短路徑計算。
app 計算 aaaaaa ict nbsp aps ces find aaaaa 沒事時看的一道題,解完後發現這居然是一個算法。 就在這裏拷貝一份,免得後面自己都忘了自己原來寫的是什麽東西。 核心思路: 1、找到臨近節點中路徑最短的那一個。 2、更新從該節點去它臨近節點的
有向無環圖路==路徑規劃
一道面試題 我們有⼀一個有向⽆無環圖,權重在節點上。 需求:從⼀一個起點開始,找到⼀一條節點權重之和最⼤大的最優路路徑。 輸⼊入: n個節點,m個路路徑,起點 輸出: 最優路路徑的權重值之和 舉例例: 3個節點與權重: A=1, B=2, C=2 3條路路徑: A->
有向無環圖DAG 拓撲排序 程式碼解釋
目錄: DAG定義 舉例描述 實際運用 演算法描述 演算法實戰 演算法視覺化 定義 在圖論中,由一個有向無環圖的頂點組成的序列,當且僅當滿足下列條件時,稱為該圖的一個拓撲排序(英語:Topological sorting)。 每個頂點出現且只出現一
Park[有向無環圖的DP]
---- From decoration #include<bits/stdc++.h> #define N 2005 #define M 5005*2 #define LL long long using namespace std;
構建有向無環圖(DAG)模型解決矩形巢狀問題 以(nyoj16為例)
DAG(Directed Acyclic Graph):在圖論中,如果一個有向圖無法從某個頂點出發經過若干條邊回到該點,則這個圖是一個有向無環圖(DAG圖)。有向無環圖上的動態規劃是學習動態規劃的基礎。很多問題都可以轉化為DAG上的最長路和最短路或計數問題。 分析
有向無環圖(DAG)技術:超越區塊鏈的分散式賬本
一、起源 DAG(Directed Acyclic Graph,有向無環圖)是一種資料結構,最早提出在區塊鏈中加入DAG概念作為演算法,是在2013年的bitcointalk論壇,被稱作為“Ghost協議”,這一提議也是為了解決當時比特幣的擴容問題。後來,在NXT社群,
NOIP模擬 有向無環圖(玄學建圖+最短路)
內網傳送門 【題目分析】 SPFA竟然有人亂搞A了?orz(蒟蒻亂搞只有40pts qwq) 很巧妙的建圖思路,將每條路徑視為一個點,從一條路徑i到達另一條路徑j,如果w[i]<w[j],那麼會產生w[j]-w[i]的費用,否則不會產生任何費用。 所以考慮將所有
環和有向無環圖
文章目錄 在和有向圖相關的實際應用中,有向環特別的重要。 優先順序限制下的排程問題:給定一組需要完成的任務,以及一組關於任務完成先後次序的優先順序限制。在滿足限制條件的前提下應該如何安排並完成所有任務? 對於任意一個這樣的問題,我們都可以畫出一張有向圖,其中頂點
在DAG(有向無環圖)上的常見推論
1.DAG上某條邊可能被經過的次數數量: 通過在DAG上的總結,再結合我們在小學學過的乘法原理,我們可以考慮到一個規律:在一條邊M(u->v)上,通過M的方法數量為從源點到達u的方式數量*從終點
Spark有向無環圖DAG圖解與演示
目錄:1、有向無環圖 2、程式碼結構 3、程式碼學習步鄹及方法 4、重點程式碼講解 5、程式碼展現 6、執行結果 ——————————————————————————————————— 1、有向無環圖 在圖論中,如果一個有向圖無法從某個頂點出發經過若干條邊回到該點,則這個
資料結構——有向無環圖(AOV網、AOE網)
有向無環圖是一個無環的有向圖, 是描述一項工程或系統的進行過程的有效工具。幾乎所有的工程都可分為若干個稱做活動的子工程。 有兩種常用的活動網路 1. AOV網(Activity On Vertices)——用頂點表示活動的網路  
圖->有向無環圖->拓撲排序
文字描述 關於有向無環圖的基礎定義: 一個無環的有向圖稱為有向無環圖,簡稱DAG圖(directed acycline graph)。DAG圖是一類較有向樹更一般的特殊有向圖。 舉個例子說明有向無環圖的應用。假如有一個表示式: ((a+b)*(b*(c+d))+(c+d)*e
在有向無環圖中求最長路徑
// A C++ program to find single source longest distances in a DAG #include <iostream> #include <list> #include <stack> #include <limit
深度優先演算法(DFS)遍歷有向無環圖計算最優路徑
遍歷有向無環圖,尋找最優路徑: 1、假設我們從A點走到B點,可以經過不同的地方,分別用1,2,3,4,5,6表示,A用0表示,B用7表示,從一個地方到另一個地方,中間的路好走的程度用w表示,w越大表示越好走,因此我們可以建立數學模型如下圖1所示: 圖1 2、根據數學模