问题描述:
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)。