無向連通圖的生成樹個數

對於一個無向連通圖來說,它可能有很多生成樹,那麼如何求得它的生成樹個數呢?
首先給出一個非常一般的計算方法 -- 矩陣行列式法

對於任何一個頂點數爲n的無向連通圖,我們列出一個矩陣。
矩陣的規則是:
1、在主對角線上的元素爲此節點的度數
2、對於其他位置上的元素Matrix(i,j) { i != j },
   (1) 如果節點i和節點j連通,則Matrix(i,j)的值爲-k,其中k值爲節點i到節點j的平行邊個數。如果此圖是一個簡單圖,即任意兩點間不存在平行邊,那麼這個值就爲-1.
   (2) 但如果節點i和節點j根本不連通,則Matrix(i,j)的值爲0。
這樣的一個矩陣Matrix就會很容易的用O(n^2)的複雜度建立。接下來如何求得這個無向連通圖的生成樹個數呢。
直接給出定理:
撤去任意一個節點的信息,求出剩下的(n-1)*(n-1)矩陣的行列式,此值即爲這個無向連通圖的生成樹個數。複雜度爲O(n^3)
下面給出一個例子:
圖1
此圖上的節點數爲n = 8,則根據上述方法,我們要列出一個8*8的矩陣,然後再消去一行,算出其行列式。

矩陣爲:(8*8)

 2  -1  -1   0   0   0   0   0
-1   1   0   0   0   0   0   0
-1   0   3  -1  -1   0   0   0
 0   0  -1   4   0  -1  -1  -1
 0   0  -1   0   1   0   0   0
 0   0   0  -1   0   1   0   0
 0   0   0  -1   0   0   1   0
 0   0   0  -1   0   0   0   1

 假如去掉第1個節點的信息,那麼也就是去掉第一行和第一列,則矩陣變爲:(7*7)

 1   0   0   0   0   0   0
 0   3  -1  -1   0   0   0
 0  -1   4   0  -1  -1  -1
 0  -1   0   1   0   0   0
 0   0  -1   0   1   0   0
 0   0  -1   0   0   1   0
 0   0  -1   0   0   0   1

 上述圖的生成樹個數可以通過求上面這個7*7矩陣的行列式算出。
 具體證明可以參考
 Algorithmic graph theory / Alan Gibbons
 Gibbons, Alan (Alan M.)

下面來看兩個問題:
問題一: TN's Kingdom I - Establishment
http://acm.pku.edu.cn/JudgeOnline/problem?id=2819

這個問題其中比較重要的一步就是求一個K階完全圖的最小生成樹的個數。
通過上述方法則可以很容易的求出其個數爲n^(n-2)個。
在上述的那本參考書中還有另一種證明方法,組合數學的方法,也可以參考參考。

問題二:Spanning trees in a fan
http://acm.hit.edu.cn/ojs/show.php?Proid=100322&Contestid=42

這個問題是給定一個特殊規定的無向連通圖,求其生成樹的個數。此問題當然可以用上述矩陣法求解,但是其點可以達到1000,那麼
O(n^3)的複雜度還是很難接受的。
但是此題非常簡單,可以用很容易的遞推搞定,也可以用上述的方法檢驗。

具體方法如下:
設ans[i]表示有i個節點時,此圖生成樹的個數。那麼我們只要找到其第i+1個節點插入後,生成樹如何變化就可以了。
如果想把第i+1個節點也加入生成樹的話,那麼只有三種連入前i個節點生成樹的方案。

1、將i與i+1節點相連
2、將0與i+1節點相連
3、將0與i+1,i與i+1都相連(這樣會多一條邊)

情況1和情況2非常好處理,都分別等於ans[i],所以遞推式先可寫爲ans[i+1] = 2*ans[i] + N(情況3);
那麼情況3又如何計算呢,其實也很簡單,由於情況3中要加入2條邊,那麼也就是說前面的模型必須要有i-1條邊(因爲0-i共有i+1個
節點,所以生成樹需要i條邊,但是要少一條,所以爲i-1條邊)。再考慮情況3中連這兩條線有什麼用處呢,很容易想到,這兩條邊
把節點0和節點i相連了起來,如果說以前的模型中已經連通這兩點,那麼就會產生衝突(0 - i必然有環,不爲樹)。那麼也就是說
要想在原來的模型上加上這兩條邊,原來的模型中節點0和節點i之間必然不連通,那麼遞推式中的N(情況3)也就是節點0與節點i不連通
的模型的個數。也就是說可以取k ( 1 <= k < i ),並且使0,1,2,……,k都連通成樹,然後k+1,k+2,……,i都連通並且和0不連通。

所以很容易的計算出N(情況3)=SUM{ans[k]} (1 <= k < i)。整個遞推公式就完成了,答案爲:
ans[i+1] = 2*ans[i] + SUM{ans[k]} (1 <= k < i);
這樣的公式我們還是很滿意,可以用O(n)的複雜度生成答案表,空間複雜度也是O(n),但是要存儲前i項ans[]和。

其實我們更可以進一步遞推,使得式子變爲更簡單。可以猜想加數學歸納法證明:
ans[i+1] = 3*ans[i] - ans[i-1];
這樣的式子是我們能得到的最滿意的式子了。

通過上面的兩道題,我們可以看出,生成樹個數的問題要看規模,在O(n^3)複雜度允許的情況下,可以使用矩陣法,如果複雜度不允許
的情況下,我們可以直接找出其遞推關係。

以上算法也正在研究中,如果有什麼不對之處,請大家批評指正:)

 

轉載自 :http://wtommy.ycool.com/post.2218850.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章