Havel-Hakimi定理很容易理解:
三步走就可以了:
比如序列:4 7 7 3 3 3 2 1
下标
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
值
|
4
|
7
|
7
|
3
|
3
|
3
|
2
|
1
|
第一步:把序列按降序排序。
下标
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
值
|
7
|
7
|
4
|
3
|
3
|
3
|
2
|
1
|
第二步:删除第一个数7。序列变成
下标
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
值
|
7
|
4
|
3
|
3
|
3
|
2
|
1
|
第三步:从头开始,数7个数,也就是下标:[1,7]把[1,7]区间里的值都减1
由于第一个数已经删除,那么序列变成这样的了:
下标
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
值
|
6
|
3
|
2
|
2
|
2
|
1
|
0
|
然后:
重复第一步:排序。
重复第二步:删除第一个数6
重复第三步:从头开始数6个数:也就是下标【1,6】,把区间【1,6】中的数删除。序列变成:
下标
|
1
|
2
|
3
|
4
|
5
|
6
|
值
|
2
|
1
|
1
|
1
|
0
|
-1
|
由于已经出现了-1,而一个点的边数(度)不可能为负数。所以,我们就可以判定序列无法构成一个图,所以此序列是不可图的。
下面再举一个例子:
已经排序:
5
|
4
|
3
|
3
|
2
|
2
|
2
|
1
|
1
|
1.
|
删除第一个数5:
4
|
3
|
3
|
2
|
2
|
2
|
1
|
1
|
1.
|
把前面5个数减1:
3
|
2
|
2
|
1
|
1
|
2
|
1
|
1
|
1.
|
排序:
3
|
2
|
2
|
2
|
1
|
1
|
1
|
1
|
1.
|
删除第一个数3:
2
|
2
|
2
|
1
|
1
|
1
|
1
|
1.
|
把前面3个数减1:
1
|
1
|
1
|
1
|
1
|
1
|
1
|
1.
|
排序:
1
|
1
|
1
|
1
|
1
|
1
|
1
|
1.
|
删除第一个数1:
1
|
1
|
1
|
1
|
1
|
1
|
1.
|
把前面1个数减1:
0
|
1
|
1
|
1
|
1
|
1
|
1.
|
排序:
1
|
1
|
1
|
1
|
1
|
1
|
0
|
删除第一个数1:
1
|
1
|
1
|
1
|
1
|
0
|
把前面1个数减1:
0
|
1
|
1
|
1
|
1
|
0
|
排序:
1
|
1
|
1
|
1
|
0
|
0
|
依此类推:到最后只剩下:
0
|
0
|
0
|
0
|
由此判断该序列是可图的。
核心代码:
bool cmp(int a,int b)
{
return a>b;
}
int n;
bool Havel_Hakimi(){
for(int i=0; i<n-1; i++)
{
sort(a+i,a+n,cmp);
if(i+a[i] >= n) return false;
for(int j=i+1; j<=i+a[i] ; j++)
{
--a[j];
if(a[j] < 0) return false;
}
}
if(a[n-1]!=0) return false;
return true;
}