问题
来源离散数学的图论中 第一个接触到的算法:Havel–Hakimi算法 (哈维尔算法)
判断一个非负序列是否为某无向简单图的度数列
的方法(Pyhton代码)
前提提要
1.无向简单图
首先先了解什么是 无向简单图:因为在一个非负序列中,若它能形成无向简单图(没有方向,且在图中,两端点相同的边称为环;两端点间的若干条边称为平行边;有环的图称为带环图,没有环的图称为无环图;有平行边的图称为多重图;没有环也没有平行边的图,称为简单图)。
2.度数列
度数列:若把图 G 所有顶点的度数排成一个序列 S,则称 S 为图 G 的度数列。
3.握手定理
在离散数学中,判断一个非负序列是否为某无向简单图的度序列主要是根据其对应的图G中是否符合欧拉提出的握手定理:设D=<V,E>为任意有向图,V={v1,v2,…,vn},|E|=q,则所有顶点的度数和=2q,且出度=入度=q。握手定理的推论: 任何图(无向的或有向的)中,奇度顶点的个数是偶数。所有顶点的度数和(2q=偶数)=偶度顶点的度数之和(偶数)+奇度点的顶点度数之和,所以偶度顶点的顶点度数之和是一个偶数,而奇数个奇数为奇数,故奇数点的个数必为偶数。
所以根据上文的推论,即是判断度数列
是否能成图的原理,相当于其能成图所需要的性质。
算法思路:
思路其实很简单:算法主要分三步:
1.排序(由大到小)。
2.删除(或置零)度序列中最大的(即第一个数)数 K ,且使后面的K个数都 -1。
ps:个人认为置零处理写代码更方便,“使后面的K个数都 -1”这个操作不会超出序列(Python列表)的总长度
3.若处理后的度数列
中出现了负数,则不能成图,若度数列
中数字都为0(因为是降序排序,则相当于第一个数不为0即可),则可以成无向最简图。
例如(递归循环处理):
度数列
:(2,3,2,1,4)
第一次处理(三步走):
1.排序之后:4 3 2 2 1
2.置0:第一个数K(K=4),将后面K(K=4)个数都 -1 即:0 2 1 1 0
3.判断:无负数,第一个数也不为0,也就进入下一次处理
第二次处理:
1.排序之后:2 1 1 0 0
2.置0:第一个数K(K=2),将后面K(K=2)个数都 -1 即: 0 0 0 0 0
3.判断:第一个数为0(即全为0),则可成无向最简图。
AC python代码:
list = [] # 生产空列表
n=int(input('请输入正整数度序列个数:')) # 度序列数字个数
for _ in range(n):
list.append(int(input())) # 向列表list(度序列)输入数字 每输入一个数字按一次回车
def havel(list):
list.sort(reverse=True) # 生成降序度序列
if list[0] == 0: # 递归终止条件:当排好序后,第一个数为0,因为是降序,则一定全为0,则可以成为最无向简图
return True
i = 1 # 跳过序列中第一个数
while i <= list[0]: # 从第二个数(脚标为1)开始,向后的N个数字都-1(N为第一个数数值 (list[0]))
list[i] -= 1
if list[i] < 0: # 如果出现负数,则不能成为最无向简图
return False
i += 1 # +1向下一个数循环
list[0] = 0 # 减完之后第一个数0(相当于删除)
if havel(list): # 递归 再进行相同的下n次操作
return True
else:
return False
x= havel(list) # 实现算法Havel–Hakimi自定义函数返回的bool值
print(x) #True 即可成图,False 不可成图