給定 為一個 undirect weighted graph
簡單講,生成樹本身會是樹,並且頂點與原圖一樣,就差它可能從原圖上拔掉了一些邊
樹本身是 acyclic 的,並且至少需要有 條邊
求 MST 即要使這些邊的成本總和最小
MST 能夠應用在城市電網佈局或是交通建設等使成本最小化的問題上,是個重要的問題
採用 greedy 的策略求出 MST
每次挑選 weight 最小的邊加入 MST ,過程中必須保證加入的邊不會使 出現 cycle
這邊,我們使用 disjoint set 來輔助檢查
我們可以將 中所有 component 視為一個 set,在檢查每次加入 會不會產生 cycle 時,相當於判斷 跟 是否在同一個 set 中,若不屬於同個 set 表示可以加入
在 unionSets
我們就會去比 find(u)
是否等於 find(v)
了
以下提供一個簡易的 disjoint set 實作:
雖然排序需要 的時間,但如果邊不多 (通常啦,課本就這樣),我們可以改說是
disjoint set 所需時間是 ,而 成長非常緩慢
所以我們直接就說時間複雜度是
也是採用 greedy 的策略,但不同的是,我們每次從 中任選一點形成集合 ,每次選取 加入 ,其中 ,想當然我們每次都挑 weight 最小的邊,並且保證 維持 connected
直到所有頂點都放入 了, 中的邊即形成一個 MST
你會發現,這演算法怎麼這麼像 Dijkstra
確實,而且他們的時間複雜度也雷同,同樣受到 priority queue 實作的影響
\ | Total | |||
---|---|---|---|---|
Array | ||||
Binary Heap | ||||
Fibonacci Heap |
這個以考試來說偏冷門
簡單來說,就是改看成一群樹 (森林),一開始樹都是只有各個頂點,我們一直合併樹的方式直到最後只剩一棵樹即為所求
它也是 greedy 策略,每次都挑成本最小的
時間複雜度也是
下面是我大致寫的,應該是對的吧…… 如果我自己沒理解錯
(我對它也不熟)
因為它真的很冷門,如果不太會可以選擇跳過
MST 選擇題之類的啊,很愛考一些觀念,舉幾個:
無向連通圖中,如果移除某頂點會圖的分量變多,該點稱為 articulation point (關節點)
去掉某頂點會使圖不連通,則稱為 cut vertex (切點)
兩者基本上是差不多的,我們以下就當一樣
cut vertex 的集合為 vertex cut (點切集)
定義 vertex connectivity (點連通度) 為最少移除多少頂點可使圖不連通
可想而知,
連通圖至少三頂點且沒有 cut vertex 時稱該圖為 biconnected
不存在 cut vertex 的無向連通圖為 biconnected graph
biconnected component 指為 biconnected graph 的 maximal induced subgraph (極大誘導子圖)
像網路結構之類的,如果有 articulation point ,表示該節點掛掉了會是大災難
所以確保其為 biconnected graph 是重要的
以下介紹找出 articulation point 的方法
最簡單的且直覺的想法,就是把每個頂點都移除看看,看會不會使圖不連通
為此需要遍歷圖 次,時間複雜度會是
以演算法來說,還有改進空間,然而對人眼判別來說,這樣的方法就相當夠用了,而且通常考試給的圖並不大
只是要你找出 articulation point 的話,用此方法反而更快
我們之前有講過如何找出所有 strongly connected component
其中 Kosaraju's algorithm 需要兩次 DFS ,而 Tarjan's algorithm 只需要一次 DFS 即可
現在,雖然問題變成無向圖,但我們依舊能使用其想法:
parent
,紀錄各頂點之 parentparent[u] == nullptr
) 並且其子點數量 ,則 為一個 articulation pointdisc
中)這邊 值是演算法核心,如果 ,表示從 的子樹沒有 back edge 可以連回 或是其 ancestors ,表示 是 articulation point
考慮下圖:
我們使用上述演算法來找出 articulation points
給定有向圖 ,其上有兩點 ,其中 稱作 source , 稱作 sink ,滿足 , 可達 且 可達 ( 的 in-degree 為 , 的 out-degree 為 )
若 則
令 為 capacity function , 為 flow function 滿足:
則稱 為一個 flow network, 為 之一 flow
定義 為 之 value
Flow network 直覺看來就像是許多管線串連的網路,它有個水源起點 , 為終點池
那麼該怎麼求出從起點所能流出的最大總流量呢 (求 上具有最大 value 之 flow)?這個問題便是 the maximum flow problem
給定 flow network ,流量為
之 residual network ,其中
而我們會稱 上 到 的 simple path 為 augmenting path
其策略即 greedy ,我們每次能挑滿就挑滿,然後去更新 residual network
先寫好前置作業
FlowNetwork
的部份我覺得其實沒特別需要寫
雖然演算法過程中要兩邊更新 但實際上更新一邊就能看出東西了 所以我就寫個樣子
再來看演算法的部份就會簡單多了
時間複雜度為 其中 即 maximum flow
例如下圖:
Note
依據原始問題的定義,每邊的 capacity 可為任意實數,但 Ford-Fulkerson method 只適用於每邊的 capacity 皆為有理數時
看上面 Ford-Fulkerson method 就會發現,這時間複雜度怎麼還跟問題答案 有關啊?
是的,這牽扯到該方法的大問題,那就是它挑 augmenting path 的方法沒有特別設計過
該方法完全有可能會不斷挑一些很爛的 augmenting path 使得執行效率大幅降低
就算圖本身很小,如果 很大,那效率還是會很爛,並且就算只是把 放大,同個網路的效率也會有所不同
考慮下面這個極端情況:
如果每次都挑到經過 再
可想而之會多跑超級多回
聽起來就不夠聰明對吧,給你挑,你一眼就知道怎麼挑
Edmonds-Karp 的想法就只差在,它在挑走哪條 augmenting path 時是用 BFS 挑的
所以他的時間複雜度為
給定 為 flow network, 為 source, 為 sink
若 為 上的 flow,下列敘述等價:
也就是說,我們上面求 maximum flow 的同時,也能解出 minimum cut
考試都有可能問,要知道這兩個問題是同一件事
Tip
為 minimum cut 且
給定 為 biparite graph (離散必考內容,不知道這是什麼的請趕快知道),若 滿足 中的邊皆不具共同端點,則稱 為 之 bipartite matching
如果想求 上的 maximum bipartite matching ,我們亦可利用解 maximum flow 的技巧
首先要把 變成一個 flow network
辦法就是在左右兩邊加 source 跟 sink ,source 連到 中所有點 sink 連到 中所有點
視所有邊 capacity 都是 ,利用 Ford-Fulkerson method 求解 之 maximum flow,所求即 之 maximum matching
因為 capacity 都 ,所以使用 Ford-Fulkerson method 的時間複雜度也就
簡單講一下為什麼可以這樣 (嘴砲證明法):
claim: 中存在一組 matching 使得 具有整數值的 flow
()
則令 ,否則令
則 為 之 flow 且可驗證得
()
給定 為 之整數值 flow ,定義
則 為 之一組 matching 且可驗證得因此欲求 之 maximum matching 相當於求 之 maximum flow
並且由於 中每邊的 capacity 皆為整數,故可以使用 Ford-Fulkerson method 求 之 maximum flow ,而得 之 maximum matching