1. 程式人生 > >關於Havel演算法判斷度數序列能否構成簡單圖的思考

關於Havel演算法判斷度數序列能否構成簡單圖的思考

問題描述:

Given a list of n natural numbers d1, d2,...,dn, show how to decide in polynomial time whether there exists an undirected graph G = (V, E) whose node degrees are precisely the numbers d1,d2,···,dn. G should not contain multiple edges between the same pair of nodes, or “ loop” edges with both endpoints equal to the same node.

該問題是從度數序列中判斷是否能構成簡單圖。首先統計度數總和是否為偶數,這是成圖的充要條件。然後根據Havel定理,假設度數序列中含有n個數,對應著n個節點,而第i個節點的度數為di。接著將節點按度數大小降序排序,之後選擇第一個節點,如果該節點度數比n大,則不能構成簡單圖;否則將第一個節點後的d1個節點逐個度數減一,這一過程可以理解為將該節點和較大的d1個節點連線,在連線的過程中如果發現某節點的度數小於0,則不能構成簡單圖。考慮完第一個節點後以後將不再考慮,剩下的節點重新按照度數降序排序,n = n -1,重複以上步驟。

以下是虛擬碼:
total_degree = sum(d)
if !total_degree % 2:
	print 'no graph'
	return -1
n = length(d)
while(n):
	sort(d)
	d1 = d[0]
	if d1 > n:
		print 'no simple graph'
		return -1
	for i = 1 to d1:
		d[i] -= 1
		if d[i] < 0:
			print 'no simple graph'
			return -1
	d[0] = 0
	n -= 1
print 'the sequence can construct a simple graph’

正確性證明:

演算法每次都選取最大度數的點是為了後面有足夠多的點可以抵消該點的度數,首先考慮該演算法排除的情況是否確實不能構成簡單圖,其排除條件包括度數總和不為偶數、最大的度數超過節點數以及連線過程出現了負數度數的點,第一個是能構成圖的充要條件,而第二個條件說明該節點必然存在環或平行邊,第三個條件表示連線了孤立節點,這是不允許的,所以圖中必然出現了環或平行邊。所以該演算法排除的情況都是不能構成簡單圖的情況。

那麼是否存在該演算法成功確定的序列卻不能構成簡單圖的情況呢?這顯然是不可能,因為任意的一個簡單圖都能轉換成每個節點連線的都是度數不小於它的節點的簡單圖,例如,首先隨機找出一個節點,連線其他d1個節點,之後就不再考慮該節點,然後在剩下的節點中找度數最大的節點,給它分配第二大的度數,即與d2個節點連線,如此類推,直到分配完所有度數。

綜上所述,該演算法是正確的。

複雜度分析:

一個遍歷中巢狀一個排序,所以演算法的時間複雜度為O(n2logn)。