一句话,顶点的度序列 Havel 定理~

定义:给出一个无向图的顶点度序列 {dn},要求判断能否构造出一个简单无向图。

分析:

    贪心的方法是每次把顶点按度大小从大到小排序,取出度最大的点Vi,依次和度较大的那些顶点Vj连接,同时减去Vj的度。连接完之后就不再考虑Vi了,剩下的点再次排序然后找度最大的去连接……这样就可以构造出一个可行解。
    判断无解有两个地方,若某次选出的Vi的度比剩下的顶点还多,则无解;若某次Vj的度减成了负数,则无解。
至于什么是Havel定理,上面这个构造过程就是了~


定理的简单证明如下:
    (<=)若d'可简单图化,我们只需把原图中的最大度点和d'中度最大的d1个点连边即可,易得此图必为简单图。
    (=>)若d可简单图化,设得到的简单图为G。分两种情况考虑:
        (a)若G中存在边,则把这些边除去得简单图G',于是d'可简单图化为G'
        (b)若存在点Vi,Vj使得i=dj,必存在k使得(Vi, Vk)在G中但(Vj,Vk)不在G中。这时我们可以令GG=G-{(Vi,Vk),(V1,Vj)}+{(Vk,Vj),(V1,Vi)}。GG的度序列仍为d,我们又回到了情况(a)。

View Code
1 #include <cstdio>
2 #include <cstring>
3 #include <algorithm>
4
5 usingnamespace std;
6
7 constint NF =2;
8 constint SIZE =1024;
9
10 int cnt[NF];
11 int deg[NF][SIZE];
12
13 bool cmp(constint& a,constint& b)
14 {
15 return a > b;
16 }
17
18 int main()
19 {
20 int cas;
21
22 scanf("%d",&cas);
23 for (int cc =0; cc < cas; cc++)
24 {
25 scanf("%d",&cnt[0]);
26 for (int i =0; i < cnt[0]; i++)
27 scanf("%d",&deg[0][i]);
28
29 sort(deg[0],deg[0] + cnt[0],cmp);
30
31 while (deg[0][cnt[0]-1] ==0&& cnt[0] >0) cnt[0]--;
32
33 int oo =0;
34 while (cnt[oo] >1)
35 {
36 sort(deg[oo],deg[oo] + cnt[oo],cmp);
37
38 if (cnt[oo] -1< deg[oo][0]) break;
39
40 cnt[1-oo] =0;
41 for (int i =1; i < cnt[oo]; i++)
42 {
43 if (i <= deg[oo][0]) deg[oo][i]--;
44 if (deg[oo][i] >0)
45 deg[1-oo][cnt[1-oo]++] = deg[oo][i];
46 }
47
48 oo =1- oo;
49 }
50
51 printf("%s\n",cnt[oo] ==0?"yes" : "no");
52 }
53 return0;
54 }