改部分来自网络:
贪心的方法是每次把顶点按度大小从大到小排序,取出度最大的点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)。
相关题:
http://162.105.81.212/JudgeOnline/problem?id=1659
输出任何一个图化序列
http://acm.hdu.edu.cn/showproblem.php?pid=2454
赤裸裸的序列图化
HDU 2454
#include<iostream> #include<algorithm> using namespace std ; const int N = 1010 ; int n,dg[N]; int cmp(int a,int b) { return a>b ; } int main() { int cas ; scanf("%d",&cas); while(cas--) { scanf("%d",&n); int tot = 0 ; for(int i=1;i<=n;i++) { scanf("%d",&dg[i]); tot += dg[i] ; } if(tot%2)//判断课图化 。。。 { printf("no/n"); continue ; } /*判断可 简单图化*/ int flag , ok = 0 ; for(int i=1;i<=n;i++) { sort(dg+i,dg+n+1,cmp) ; if(dg[i] > n-i) { ok = 1 ; break ; } flag = 0 ; for(int j=i+1;dg[i]>0;j++,dg[i]--) { if((--dg[j]) < 0) { flag = 1 ; break; } } if(flag==1) { ok = 1 ; break ; } } if(ok) printf("no/n"); else printf("yes/n"); } return 0 ; }