关于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)。

时间: 2024-10-12 07:46:10

关于Havel算法判断度数序列能否构成简单图的思考的相关文章

Havel–Hakimi algorithm(判断度数序列是否可图)

问题 J: Degree Sequence of Graph G 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Wang Haiyang is a strong and optimistic Chinese youngster. Although born and brought up in the northern inland city Harbin, he has deep love and yearns for the boundless oceans. After gr

微软算法100题09 判断整数序列是不是二元查找树的后序遍历结果

9. 判断整数序列是不是二元查找树的后序遍历结果题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回true,否则返回false.例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果:8/ \6 10/ \ / \5 7 9 11因此返回true.如果输入7.4.6.5,没有哪棵树的后序遍历的结果是这个序列,因此返回false. 思路:如果一个数组为BST的后序遍历结果 则最后一个元素必然为该BST的根节点 因为BST的特性是左子树必然全部小

数据结构与算法问题 判断两序列是否为同一二叉搜索树序列

题目描述: 判断两序列是否为同一二叉搜索树序列 输入: 开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接下去一行是一个序列,序列长度小于10,包含(0~9)的数字,没有重复数字,根据这个序列可以构造出一颗二叉搜索树. 接下去的n行有n个序列,每个序列格式跟第一个序列一样,请判断这两个序列是否能组成同一颗二叉搜索树. 输出: 如果序列相同则输出YES,否则输出NO 样例输入: 2 567432 543267 576342 0 样例输出: YES NO 来源:

9判断整数序列是不是二元查找树的后序遍历结果

转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4252095.html 声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明.谢谢. 题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回true,否则返回false. 解题思路: 1.输入一个整型数组a,根据该数组创建二

【编程题目】判断整数序列是不是二元查找树的后序遍历结果,如果是,构建该二元查找树

判断整数序列是不是二元查找树的后序遍历结果题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回 true,否则返回 false.例如输入 5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果:8/ \6 10/ \ / \5 7 9 11因此返回 true.如果输入 7.4.6.5,没有哪棵树的后序遍历的结果是这个序列,因此返回 false. 做这个题目的时候最开始傻了,想着从前到后根据数字的大小关系判断.后来幡然醒悟,根据后序遍历的特点.序列最后一

编程算法 - 判断二叉树是不是平衡树 代码(C)

判断二叉树是不平衡树 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入一颗二叉树的根结点, 判断该树是不是平衡二叉树. 二叉平衡树: 任意结点的左右子树的深度相差不超过1. 使用后序遍历的方式, 并且保存左右子树的深度, 进行比较. 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <std

华为机试题 二叉查搜索树 判断两序列是否为同一二叉搜索树序列

描述: 判断两序列是否为同一二叉搜索树序列 输入 开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接下去一行是一个序列,序列长度小于10,包含(0~9)的数字,没有重复数字,根据这个序列可以构造出一颗二叉搜索树. 接下去的n行有n个序列,每个序列格式跟第一个序列一样,请判断这两个序列是否能组成同一颗二叉搜索树. 输出: 如果序列相同则输出YES,否则输出NO 样例输入: 2 567432 543267 576342 0 样例输出: YES NO 本题思路:根

隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率

隐马尔科夫模型HMM(一)HMM模型 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数(TODO) 隐马尔科夫模型HMM(四)维特比算法解码隐藏状态序列(TODO) 在隐马尔科夫模型HMM(一)HMM模型中,我们讲到了HMM模型的基础知识和HMM的三个基本问题,本篇我们就关注于HMM第一个基本问题的解决方法,即已知模型和观测序列,求观测序列出现的概率. 1. 回顾HMM问题一:求观测序列的概率 首先我们回顾下HMM模型的问题一.这个

[算法]判断兄弟单词

一个单词单词字母交换,可得另一个单词,如army->mary,成为兄弟单词.提供一个单词,在字典中找到它的兄弟.描述数据结构和查询过程. #include <iostream> #include <string> #include <cstring> using namespace std; void add(unsigned int count[],char c){ if(c <= 'Z'){ ++count[c - 'A']; } else{ ++cou