链接
http://poj.org/problem?id=1659
havel-hakimi定理
先定义"Graphic":
一个非负整数组成的有限序列如果是某个无向图的度序列,则称该序列是可图的(Graphic)
定理内容:
由非负整数组成的非增序列
s
:
d
1
,
d
2
,
.
.
.
,
d
n
s:d_1,d_2,...,d_n
s:d1,d2,...,dn是可图的,当且仅当序列
s
′
:
d
2
−
1
,
d
3
−
1
,
.
.
.
,
d
d
1
−
1
,
.
.
.
,
d
n
s':d_2-1,d_3-1,...,d_{d_1-1},...,d_n
s′:d2−1,d3−1,...,dd1−1,...,dn是可图的
分析:
显然这是一个递归的定义,而且显然只包含一个
0
0
0的序列是可图的
构造方法:
不断地对序列进行排序,然后每次取开头的元素,并将它从序列中剔除,假设其度为
d
d
d,则用这个顶点连接边到序列的前
d
d
d个数字代表的结点
只要中间不会出现负数,而且每个
d
d
d都能用完,那最终肯定能到达序列
0
0
0
代码
#include <iostream>
#include <cctype>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 110
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
ll N, a[maxn], mat[maxn][maxn], num[maxn];
bool cmp(ll x, ll y){return a[x]>a[y];}
ll read(ll x=0)
{
ll c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
int main()
{
ll T=read(), i, j;
bool flag;
while(T--)
{
cl(mat);
N=read();
for(i=1;i<=N;i++)a[i]=read(), num[i]=i;
flag=true;
for(i=1;i<=N;i++)
{
sort(num+i,num+N+1,cmp);
for(j=i+1;j<=N and a[num[i]];j++)
{
a[num[i]]--;
a[num[j]]--;
mat[num[i]][num[j]]=mat[num[j]][num[i]]=1;
if(a[num[j]]<0)flag=false;
}
if(a[num[i]]>0)flag=false;
}
if(flag)
{
printf("YES\n");
for(i=1;i<=N;i++)
{
for(j=1;j<=N;j++)
{
printf("%lld",mat[i][j]);
putchar(j==N?10:32);
}
}
}
else printf("NO\n");
putchar(10);
}
return 0;
}