Havel定理描述
给定一个非负整数序列{d1,d2,...dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。进一步,若图为简单图,则称此序列可简单图化。
可图化的判定比较简单:d1+d2+...dn=0(mod2)。关于具体图的构造,我们可以简单地把奇数度的点配对,剩下的全部搞成自环。
可简单图化的判定,有一个Havel定理,是说: 我们把序列排成不增序,即d1>=d2>=...>=dn,则d可简单图化当且仅当d'=(d2-1, d3-1, ... d(d1+1)-1, d(d1+2), d(d1+3), ... dn)可简单图化。这个定理写起来麻烦,实际上就是说,我们把d排序以后,找出度最大的点(设度为d1),把它和度次大的d1个点之间连边,然后这个点就可以不管了,一直继续这个过程,直到建出完整的图,或出现负度等明显不合理的情况。
给定一个非负整数序列{d1,d2,...dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。进一步,若图为简单图,则称此序列可简单图化。
可图化的判定比较简单:d1+d2+...dn=0(mod2)。关于具体图的构造,我们可以简单地把奇数度的点配对,剩下的全部搞成自环。
可简单图化的判定,有一个Havel定理,是说: 我们把序列排成不增序,即d1>=d2>=...>=dn,则d可简单图化当且仅当d'=(d2-1, d3-1, ... d(d1+1)-1, d(d1+2), d(d1+3), ... dn)可简单图化。这个定理写起来麻烦,实际上就是说,我们把d排序以后,找出度最大的点(设度为d1),把它和度次大的d1个点之间连边,然后这个点就可以不管了,一直继续这个过程,直到建出完整的图,或出现负度等明显不合理的情况。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxm=20;
int edge[maxm][maxm];
struct node
{
int degree;
int index;
}v[maxm];
int cmp(node p,node q)
{
return p.degree>q.degree;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
memset(edge,0,sizeof(edge));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&v[i].degree);
v[i].index=i;
}
sort(v,v+n,cmp);
int ok=1;
for(int k1=0;k1<n;k1++)
{
sort(v,v+n,cmp);
int id=v[k1].degree;
int i=v[k1].index;
if(id>n-k1-1)
{
ok=0;
break;
}
for(int k2=1;k2<=id;k2++)
{
int j=v[k1+k2].index;
if(v[k1+k2].degree<=0)
{
ok=0;
break;
}
v[k1+k2].degree--;
edge[i][j]=edge[j][i]=1;
}
}
if(ok)
{
printf("YES\n");
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(j==0)
{
printf("%d",edge[i][j]);
}
else
{
printf(" %d",edge[i][j]);
}
}
printf("\n");
}
}
else
{
printf("NO\n");
}
if(t)
{
printf("\n");
}
}
return 0;
}