可图性判定--Havel-Hakimi定理

两个概念

1、度序列

  若把图G所有顶点的度数排成一个序列S,则称S为图G的度序列。

2、序列是可图的

  一个非负整数组成的序列如果是某个无向图的度序列,则称该序列是可图的。



Havel-Hakimi定理

由非负整数组成的非增序列S:d1, d2 ,..., dn (n≥2,d1≥1)是可图的,当且仅当序列S1:d2-1,d3-1,...,dd1+1-1,dd1+2,...,dn是可图的。其中,序列S1中有n-1个非负整数,S序列中d1后的前d1个度数(即d2~dd1+1)减1后构成S1中的前d1个数。



应用:POJ 1659 Frogs‘ Neighborhood

http://poj.org/problem?id=1659

贴上一个博客

http://blog.csdn.net/monkey_little/article/details/6358601

对于该题目中的第一个序列,分析如下:

具体操作时候,每次都把排序好的序列第一个元素处理完以后就置为0,加入到队列的最后。若是最后元素全为0,则该序列是可图的。若在中间出现某个元素减一之后变为负的,则说明此序列是不可图的。

我的AC代码如下:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #define MAXN 10
 5 typedef struct Company
 6 {
 7   int data;
 8   int no;
 9 }Company;
10 Company x[MAXN];
11 int map[MAXN][MAXN];
12 int Compare(const void *elem1, const void *elem2)
13 {
14   Company *p1 = (Company*)elem1;
15   Company *p2 = (Company*)elem2;
16 //  if (p1->data == p2->data)
17 //  {
18 //    return p1->no - p2->no;
19 //  }
20   return p2->data - p1->data;
21 }
22 int main()
23 {
24   int T, N;
25   scanf("%d", &T);
26   while(T--)
27   {
28     scanf("%d", &N);
29     memset(map, 0, sizeof(map));
30     int flag = 0;
31     for (int i = 0; i < N; ++i)
32     {
33       scanf("%d", &x[i].data);
34       x[i].no = i;
35     }
36     qsort(x, N, sizeof(Company), Compare);
37     while(!flag && x[0].data)
38     {
39       int start = x[0].data;
40       for (int i = 1; i < start+1; ++i)
41       {
42         x[i].data--;
43         if (x[i].data < 0)
44         {
45           flag = 1;
46           break;
47         }
48         map[x[0].no][x[i].no] = 1;
49         map[x[i].no][x[0].no] = 1;
50       }
51       x[0].data = 0;
52       qsort(x, N, sizeof(Company), Compare);
53     }
54     if (flag)
55     {
56       printf("NO\n");
57     }else
58     {
59       printf("YES\n");
60       for (int i = 0; i < N; ++i)
61       {
62         for (int j = 0; j < N; ++j)
63         {
64           printf(j == 0 ? "%d" : " %d", map[i][j]);
65         }
66         printf("\n");
67       }
68     }
69     if (T)
70     {
71       printf("\n");
72     }
73   }
74   return 0;
75 }

x.no这个属性用来记录每个输入数据的输入时的编号次序,以用来在map[][]数组填充1时用,否则不知道该x[?][?] = 1;

flag是一个标志位,若中间有负数出现,就改变其值

思路源自以下代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 struct node
 6 {
 7     int num,e;
 8 }x[15];
 9 bool map[15][15];
10 int cmp(node a,node b)
11 {
12     if(a.num==b.num)
13         return a.e<b.e;
14     return a.num>b.num;
15 }
16 int judge(int n)
17 {
18     int i,num,tmp;
19     while(1){
20         sort(x+1,x+n+1,cmp);
21         if(!x[1].num)
22             return 1;//数组全为 0 的情况退出
23         for(i=2;i<=x[1].num+1;i++){
24             if(x[i].num>0){
25                 x[i].num--;
26                 map[x[1].e][x[i].e]=map[x[i].e][x[1].e]=1;
27             }
28             else
29                 return 0;
30         }
31         x[1].num=0;
32     }
33 }
34 int main()
35 {
36     int n,t,i,j;
37     bool flag;
38     scanf("%d",&t);
39     while(t--){
40         scanf("%d",&n);
41         for(i=1;i<=n;i++){
42             scanf("%d",&x[i].num);
43             x[i].e=i;
44         }
45         memset(map,0,sizeof(map));
46         flag=judge(n);
47
48         if(flag){
49             printf("YES/n");
50             for(i=1;i<=n;i++){
51                 for(j=1;j<=n;j++)
52                     printf(j==1?"%d":" %d",map[i][j]);
53                 printf("/n");
54             }
55         }
56         else
57             printf("NO/n");
58         if(t)
59             printf("/n");
60     }
61     return 0;
62 }

可图性判定--Havel-Hakimi定理,布布扣,bubuko.com

时间: 2024-10-12 02:59:24

可图性判定--Havel-Hakimi定理的相关文章

POJ 1659 Frogs&#39; Neighborhood(可图性判定—Havel-Hakimi定理)【超详解】

Frogs' Neighborhood Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 9897   Accepted: 4137   Special Judge Description 未名湖附近共有N个大小湖泊L1, L2, ..., Ln(其中包括未名湖),每个湖泊Li里住着一只青蛙Fi(1 ≤ i ≤ N).如果湖泊Li和Lj之间有水路相连,则青蛙Fi和Fj互称为邻居.现在已知每只青蛙的邻居数目x1, x2, ..

POJ 1659 Frogs&#39; Neighborhood 可图性判断-Havel定理

Description 未名湖附近共有N个大小湖泊L1, L2, ..., Ln(其中包括未名湖),每个湖泊Li里住着一只青蛙Fi(1 ≤ i ≤ N).如果湖泊Li和Lj之间有水路相连,则青蛙Fi和Fj互称为邻居.现在已知每只青蛙的邻居数目x1, x2, ..., xn,请你给出每两个湖泊之间的相连关系. Input 第一行是测试数据的组数T(0 ≤ T ≤ 20).每组数据包括两行,第一行是整数N(2 < N < 10),第二行是N个整数,x1, x2,..., xn(0 ≤ xi ≤ N

度序列可图性判断(Havel-Hakimi定理)

Havel定理描述 给定一个非负整数序列{d1,d2,-dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化.进一步,若图为简单图,则称此序列可简单图化. 可图化的判定比较简单: $d_1 + d_2 + d_3 +-+d_n = 0(mod2)$ $n-1geq d_{max}$ 关于具体图的构造,我们可以简单地把奇数度的点配对,剩下的全部搞成自环. 可简单图化的判定,有一个Havel定理,是说: 我们把序列排成不增序,即d1>=d2>=->=dn,则d可简单图化

Poj 1659 Frogs&#39; Neighborhood 图的可图性判断

/* 先将所有度数按从大到小排序,取最大的度数为N的节点,将其后面N个节点的度数减一,如果出现负数节点或者后面的节点数量不足N则可以判定无法构成图,重复这个过程,直到所有的度数都为零*/#include <cstdio> #include <iostream> #include <cstdlib> #include <algorithm> #include <set> #include <map> #include <vecto

序列可图化判定及顶点着色

1.度序列可图化问题 可图化的度序列其表示的图并不唯一,即画出来的图有可能不是同构体,主要原因是由度序列产生生成矩阵的时候方法并不唯一. 例子:度序列 [3 4 2 3 4 2] 图1 图2 注意度数为3 的两个顶点在图1中并不连接,在图2中却相连,说明图1图2不是同构. 对于可图化序列的简单图绘制需要用到生成矩阵,表示了随着顶点数增加而图拓展的过程.距离如下,度序列为 ,其相应的度序列矩阵为    生成矩阵的第i行等于度序列矩阵的第i行减去它的第i+1行得到,若度序列矩阵出现负值,则该序列不可

HDU 2454 Degree Sequence of Graph G (可简单图化的判定 havel定理)

题目链接:HDU 2454 Degree Sequence of Graph G 题意:给出N个点的度(简单图),问能能否画出个图,(其实就是给出一个串非负的序列是否有对应的图存在) 没见过这个定理 题意真的难懂. havel定理就是一个给出一串非负的序列,存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化.简单图的话就是,可简单图化. 可简单图化的判定(Havel定理):把序列排成不增序,即d1>=d2>=-->=dn,则d可简单图化当且仅当d'={d2-1,d3-1,-

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

[ZOJ 1015]Fishing Net(MCS弦图的判定)

Description In a highly modernized fishing village, inhabitants there make a living on fishery. Their major tools, fishing nets, are produced and fixed by computer. After catching fishes each time, together with plenty of fishes, they will bring back

poj1637 Sightseeing tour 混合图欧拉回路判定

传送门 第一次做这种题, 尽管ac了但是完全不知道为什么这么做. 题目就是给一些边, 有向边与无向边混合, 问你是否存在欧拉回路. 做法是先对每个点求入度和出度, 如果一条边是无向边, 就随便指定一个方向, 然后连一条边, 权值为1. 最后统计入度出度, 如果一个点的(入度-出度)%2==1, 就说明不存在欧拉回路. 如果全都满足, 就判断每个点的入度出度的大小关系, 入度>出度, 就向汇点连一条边, 权值为(入度-出度)/2, 相反的话就向源点连边. 跑一遍最大流, 看是否满流, 如果满流就说