POJ1659 Frogs' Neighborhood(Havel定理)

给一个无向图的度序列判定是否可图化,并求方案:

  • 可图化的判定:d1+d2+……dn=0(mod 2)。关于具体图的构造,我们可以简单地把奇数度的点配对,剩下的全部搞成自环。
  • 可简单图化的判定Havel定理):把序列排成不增序,即d1>=d2>=……>=dn,则d可简单图化当且仅当d’={d2-1,d3-1,……d(d1+1)-1, d(d1+2),d(d1+3),……dn}可简单图化。简单的说,把d排序后,找出度最大的点(设度为d1),把它与度次大的d1个点之间连边,然后这个点就可以不管了,一直继续这个过程,直到建出完整的图,或出现负度等明显不合理的情况。

这一题把青蛙看成点,邻居关系看成边,可以知道这是简单图(无重边、自环)。因此用Havel定理来判定,并且用上述方法来构造出一个解:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 struct Frog{
 7     int pos,deg;
 8     bool operator<(const Frog &f)const{
 9         return deg>f.deg;
10     }
11 }frog[11];
12 
13 int n;
14 bool ans[11][11];
15 bool Havel(){
16     for(int i=0; i<n; ++i){
17         sort(frog+i,frog+n);
18         for(int j=1; j<=frog[i].deg; ++j){
19             if(i+j>=n || frog[i+j].deg==0) return 0;
20             --frog[i+j].deg;
21             ans[frog[i].pos][frog[i+j].pos]=ans[frog[i+j].pos][frog[i].pos]=1;
22         }
23     }
24     return 1;
25 }
26 
27 int main(){
28     int t;
29     scanf("%d",&t);
30     while(t--){
31         scanf("%d",&n);
32         for(int i=0; i<n; ++i){
33             scanf("%d",&frog[i].deg);
34             frog[i].pos=i;
35         }
36         memset(ans,0,sizeof(ans));
37         if(Havel()){
38             puts("YES");
39             for(int i=0; i<n; ++i){
40                 for(int j=0; j<n; ++j){
41                     printf("%d ",ans[i][j]);
42                 }
43                 putchar('
');
44             }
45         }else{
46             puts("NO");
47         }
48         putchar('
');
49     }
50     return 0;
51 }
原文地址:https://www.cnblogs.com/WABoss/p/4941111.html