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('\n'); 44 } 45 }else{ 46 puts("NO"); 47 } 48 putchar('\n'); 49 } 50 return 0; 51 }