圖的匹配問題與最大流問題(四)——計算圖的邊連通度和點連通度

最近有點忙,好久沒跟進了,有興趣的朋友可以先熟悉下前三篇文章內容,(一)講述了基礎概念;(二)介紹了最大流算法的實現原理以及證明(三)用Java語言予以了實現,歡迎大家批評指正。

回到正題,首先介紹下什麼是圖的邊連通度和點連通度。一般來說,點連通度是指對應一個圖G,對於所有點集U屬於V(G),也就是V(G)的子集中,使得G-U要麼是一個非連通圖,要麼就是一個平凡圖(即僅包含一個獨立點的圖),其中最小的集合U的大小就是圖G的點連通度,有時候也直接稱爲圖的連通度。通俗點說,就是一個圖G最少要去掉多少個點會變成非連通圖或者平凡圖。當然對於一個完全圖來說Kn來說,它的連通度就是n-1。

同理,邊連通度就是對於一個非平凡圖G,至少去掉多少條邊才能使得該圖變成非連通圖。我們的問題就是,對於任意一個圖,如何求該圖的連通度以及邊連通度?這跟最大流問題有什麼聯繫?

簡單起見,我們先說如何求一個圖的邊連通度lamda(G)。(基於無向圖考慮)

對於圖G,設u,v是圖G上的兩個頂點,定義r(u,v)爲刪除最少的邊,使得u到v之間沒有通路。將圖G轉換成一個流網絡H,u爲源點,v是匯點,邊容量均爲1,那麼顯然r(u,v)就是流網絡的最小割,根據(二)裏的介紹,其等於流網絡的最大流。

但是,目前爲止我們還沒解決完問題,因爲顯然我們要求的邊連通度lamda(G)是所有的點對<u,v>對應的r(u,v)中最小的那個值。這樣的話我們就必須遍歷所有的點對,遍歷的的複雜度爲O(n*n)。這顯然代價太高,而事實上,我們也不必遍歷所有點對。


如圖所示,設S爲圖G的最小割集,那麼lamda(G)=|S|。設在取任意一個點u,若u在L內,那麼必然至少存在一個點v,使得r(u,v)=|S|(v是在R內時即成立)。所以,我們只需要任取一個點u,計算u和其他點的r(u,v),取最小者,必然是等於最小割集,即邊連通度。

public class EdgeConnectivity {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		double graph[][]={{0,1,0,1,0,0},
				  {1,0,1,0,1,0},
				  {0,1,0,0,0,1},
				  {1,0,0,0,1,0},
				  {0,1,0,1,0,1},
				  {0,0,1,0,1,0}};
		double graph2[][]={
				  {0,1,1,1,1,1},
				  {1,0,1,1,1,1},
				  {1,1,0,1,1,1},
				  {1,1,1,0,1,1},
				  {1,1,1,1,0,1},
				  {1,1,1,1,1,0}};
		System.out.println(edgeConnectivity(graph2));

	}
	
	
	public static int edgeConnectivity(double graph[][])
	{
		double min=Double.MAX_VALUE;
		for(int i=1;i<graph.length;i++)
		{
			double maxflow=FordFulkerson.edmondsKarpMaxFlow(graph, 0, i);
			if(maxflow<min)
				min=maxflow;
		}
		return (int)min;
	}

}


對於點連通度來說,可能就要複雜點了。求點連通度的方法就是轉換爲求邊連通度,所以就需要我們巧妙的去構造一個流網絡,使得其邊連通度等於我們原來的圖的點連通度。構造流網絡N:

若G爲無向圖:

(1) 原 G 圖中的每個頂點 v 變成 N 網中的兩個頂點 v' 和 v" ,頂點 v' 至 v" 有一條弧(有向邊)連接,弧容量爲 1;
(2) 原 G 圖中的每條邊 e = uv ,在 N 網中有兩條弧 e’= u"v',e"=v"u' 與之對應, e' 弧容量爲 ∞ , e" 弧容量爲 ∞
(3) 求該網絡的邊連通度

若 G 爲有向圖:
(1) 原 G 圖中的每個頂點變成 N 網中的兩個頂點 v’ 和 v” ,頂點 v' 至 v” 有一條弧連接,弧容量爲 1
(2) 原 G 圖中的每條弧 e = uv 變成一條有向軌 u'u"v'v" ,其中軌上的弧 u"v' 的容量爲 ∞;

如下圖所示,原圖G:


轉換後的流網絡N:



Ok,如何在流網絡N上求邊連通度呢?按照我們求邊連通度的做法,選定一個點u作爲源點,然後遍歷<u,v>點對,其中v!=u。但是在這裏源點的選擇必須是u‘’,也就是說必須是拆分後的後點,也就是兩個撇的點。匯點的遍歷只能是前點,也就是一個撇的點。爲什麼呢?很簡單,比如若u’爲源點,那麼最大流只能是1,因爲只有一條有向邊從u‘連接到u’‘,切其容量爲1。同理,若v‘’爲匯點,那麼最大流也只能是1,因爲只有(v’,v'')的有向邊指向v‘’,且容量爲1。

這樣,我們也就更容易理解爲什麼是採用上面的策略來轉換到流網絡N了吧。代碼就不上了,和求邊連通度很類似。




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