生成樹相關問題整理

2021-09-25 06:33:10 字數 2863 閱讀 7594

摘要:

在對最小生成樹演算法有一定理解後,我們對典型的最小生成樹題型應該不難解決,但是對於由最小生成樹模型變形而來的幾種模型,我們仍需做一次總結與記錄。

首先我們需要提出最小生成樹幾個性質,便於推導演算法;然後我們將介紹6種最小生成樹相關問題模型,並討論一般解法與更優解法;其中有的解法顯而易見,接受起來也很簡單,但有的解法卻需要從理論上邏輯嚴密的進行推導,構造演算法並證明演算法的正確性,這部分難度稍大。

這6個相關問題分別是:增量最小生成樹,最小瓶頸生成樹,最小瓶頸路,每對節點的最小瓶頸路,次小生成樹,最小有向生成樹。

圖論中的2個性質:

在此不給出證明。

增量最小生成樹

問題描述:

從包含n個點的空圖開始,依次加入m條帶權邊。每加入一條邊,輸出當前圖中的最小生成樹權值(如果當前圖不連通,則輸出無解)。

解題思路:

如果每次重新求完整的最小生成樹問題,總時間複雜度高達o(m^2 log n)。根據迴路的性質,可以得到如下改進演算法:

每次求出新的最小生成樹後,把其它的邊刪除。由於每次只需計算乙個n條邊(原生成樹有 n - 1條,新加入一條)的圖的最小生成樹,kruskal演算法的時間複雜度降為o(n log n),總時間複雜度為o(nm log n)。

這個演算法可以進一步改進:

加入一條邊e = (u, v)之後,圖中恰好包含乙個環。根據迴路性質,刪除該回路上權值最大的邊即可,因此只需在加邊之前的mst上找到u到v的唯一路徑上的權值最大的邊,再和e比較,刪除權值較大的一條。由於路徑唯一,可以用dfs或bfs找到這條u到v的路徑,總時間複雜度為o(nm)。

最小瓶頸生成樹

問題描述:

給出加權無向圖,求一棵生成樹,使得最大邊權值盡量小。

解題思路:

由於只關心最大邊權值,我們可以從乙個空圖開始,按照權值從小到大的順序依次加入各條邊,則圖第一次連通時,該圖的最小生成樹就是原圖的最小瓶頸生成樹。可以發現,原圖的最小生成樹就是一棵最小瓶頸生成樹(但不是每棵最小瓶頸生成樹都是最小生成樹)。

最小瓶頸路

問題描述:

給定加權無向圖的兩個節點u和v,求出從u到v的一條路徑,使得路徑上最長邊盡量短。

解題思路:

這個問題可以用二分法+bfs解決,但我們有更好的演算法。先求出這個圖的最小生成樹,則起點和終點在樹上的唯一路徑就是我們要找的路徑,這條路徑上的最長邊就是問題的答案。

每對結點間的最小瓶頸路

問題描述:

給出加權無向圖,求每兩個節點u和v之間的最小瓶頸路的最大邊長f(u,v)。

解題思路:

先求最小生成樹。接下來,用dfs把最小生成樹變成有根樹,同時計算f(u,v),當新訪問乙個節點u時,考慮所有已經訪問過的老節點x,更新f(x,u) = max(f(x,v) , w(u,v)),其中v是u的父節點。每個f(u,v)只需經過常數時間計算,因此是時間複雜度為o(n^2)。

次小生成樹

問題描述:

把所有生成樹按照權值之和從大到小的順序排列,求排在第二位的生成樹。注意,如果最小生成樹不唯一,次小生成樹的權值與最小生成樹相同。

解題思路:

次小生成樹不會與最小生成樹完全相同,因此可以列舉最小生成樹中不在次小生成樹**現的邊。注意最小生成樹只有n-1條邊,所以只需列舉n-1次。每次在剩下的邊裡求一次最小生成樹,則這n-1棵「缺一條邊的圖」的最小生成樹中權最小的就是原圖的次小生成樹。

還有一種更好的方法:

列舉要加入哪條新邊。在最小生成樹上加一條邊u-v之後,圖上會出現一條迴路,因此刪除的邊必須在最小生成樹上u到v的路徑上,且是這條路徑上的最長邊。可以證明,次小生成樹一定可以由最小生成樹加一條邊再刪一條邊得到(稱為邊交換),因此只需按照「每對節點之間的最小瓶頸路」的方法求出每對節點u和v在最小生成樹中唯一路徑的最大邊權maxcost[u][v],則剩下的部分只需要o(m)時間(列舉所有m-n+1條邊進行交換,每次花o(1)時間求出新生成樹的權值)。總時間複雜度為o(n^2)。

最小有向生成樹

問題描述:

給定乙個有向帶權圖g和其中乙個節點u,找出乙個以u為根節點,權和最小的有向生成樹。有向生成樹(directed spanning tree)也叫樹形圖(arborescence),是指乙個類似樹的有向圖,滿足以下條件:

不難發現,如果樹形圖的節點數為n,它的邊數一定為n-1,且樹形圖中不存在有向環。

解題思路:

固定根的最小樹形圖可以用朱-劉演算法解決。

首先是預處理,刪除自環並判斷根節點是否可以到達其它所有節點。如果不是,輸出無解並終止程式。

接下來是演算法的主過程:

首先,給所有非根節點擊擇一條權最小的入邊。如果選出來的n-1條邊不構成圈,則可以證明這些邊就形成了乙個最小樹形圖,否則把每個圈各收縮成乙個點,繼續上述過程。

縮圈之後,圈上所有邊都消失了,因此在最終答案裡需要加上這些邊權之和。但這樣做有個問題:假設在演算法的某次迭代中,把圈c收縮為人工節點v,則在下一次迭代中,給v選擇的入弧將與在圈c中的入弧發生衝突。(假設x在圈中已經有了入弧y->x)因此如果收縮之後又選了乙個入弧z->x,必須把弧y->x從最小樹形圖中刪除。這等價於把弧z->x的權值減少了y->x的權值。

參考書目

集合相關問題整理

1.集合的型別為什麼不能指定為基本資料型別?如 listlist new arraylist 答 集合中存放的可都是物件的引用,實際內容都在堆上面或者方法區裡面,但是基本資料型別是在棧上分配空間的,隨時就被收回的。但是通過自動包裝類就可以把基本型別轉為物件型別,存放引用就解決了這個問題。2.集合中存...

opencv相關問題整理(1)

1.如何將mat 轉換成iplimage,或者iplimage轉換成mat?iplimage cvgetimage const cvarr arr,iplimage image header cvmat cvgetmat const cvarr arr,cvmat header,int coi nu...

mysql 自增列相關問題整理

mysql自增列 1.關鍵字 auto increment 2.自增用法 例 create table animals id mediumint not null auto increment,name char 30 not null,primary key id 3.關於自增 q 怎麼獲得當前的...