Time Limit: 5000MS   Memory Limit: 10000K
Total Submissions: 9293   Accepted: 3921   Special Judge

Description

未名湖附近共有N个大小湖泊L1L2, ..., Ln(其中包括未名湖),每个湖泊Li里住着一只青蛙Fi(1 ≤ i ≤ N)。如果湖泊LiLj之间有水路相连,则青蛙FiFj互称为邻居。现在已知每只青蛙的邻居数目x1x2, ..., xn,请你给出每两个湖泊之间的相连关系。

Input

第一行是测试数据的组数T(0 ≤ T ≤ 20)。每组数据包括两行,第一行是整数N(2 < N < 10),第二行是N个整数,x1x2,..., xn(0 ≤ xi ≤ N)。

Output

对输入的每组测试数据,如果不存在可能的相连关系,输出"NO"。否则输出"YES",并用N×N的矩阵表示湖泊间的相邻关系,即如果湖泊i与湖泊j之间有水路相连,则第i行的第j个数字为1,否则为0。每两个数字之间输出一个空格。如果存在多种可能,只需给出一种符合条件的情形。相邻两组测试数据之间输出一个空行。

Sample Input

3
7
4 3 1 5 4 2 1 
6
4 3 1 4 2 0 
6
2 3 1 1 2 1 

Sample Output

YES
0 1 0 1 1 0 1 
1 0 0 1 1 0 0 
0 0 0 1 0 0 0 
1 1 1 0 1 1 0 
1 1 0 1 0 1 0 
0 0 0 1 1 0 0 
1 0 0 0 0 0 0 

NO

YES
0 1 0 0 1 0 
1 0 0 1 1 0 
0 0 0 0 0 1 
0 1 0 0 0 0 
1 1 0 0 0 0 
0 0 1 0 0 0 

 

解题思路:Havel-Hakimi定理:
1,一个非负整数组成的有限序列如果是某个无向图的序列,则称该序列是可图的。

两个无法构图判定:

排序后,最大度数超过剩下的顶点数;或者对最大度数后d1个度数减一后,出现负数;

2,判定过程:
(1)对当前数列排序,使其呈非递增序列
(2)从第二个数开始对其后d[1]个数字减1,d[1]代表排序后第1个数的值
(3)然后删除第一个之后对剩下的数继续排序
(3)一直循环直到当前序列出现负数(即不是可图的情况)或者当前序列全为0 (可图)时退出。
  
3,举例:
序列S:7,7,4,3,3,3,2,1  
删除序列S的首项 7 ,对其后的7项每项减1,
得到:6,3,2,2,2,1,0,
继续删除序列的首项6,
对其后的6项每项减1,
得到:2,1,1,1,0,-1,
到这一步出现了负数,因此该序列是不可图的

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
const int N=25;
struct node
{
    int degree;
    int num;
} v[N];
int cmp(const void *a,const void *b)
{
    return((node*)b)->degree-((node*)a)->degree;
}
int e[N][N];
int main()
{
    int t,n;
    int flag;
    int i,j,h;
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(e,0,sizeof(e));

        for(i=0; i<n; i++)
        {
            cin>>v[i].degree;
            v[i].num=i;
        }
        flag=1;
        for(int k=0; k<n&&flag; k++)
        {
            qsort(v+k,n-k,sizeof(node),cmp);
            i=v[k].num;
            j=v[k].degree;
            if(j>n-k-1) flag=0;
            for(int r=1; r<=j&&flag; r++)//对当前最大度数j后的j个数进行判定减一;
            {
                h=v[k+r].num;
                if(v[k+r].degree<=0) flag=0;//减一前为0;减一肯定为负
                v[k+r].degree--;
                e[i][h]=e[h][i]=1;//构建边;
            }
        }
        if(flag)
        {
            cout<<"YES"<<endl;
            for(int p=0; p<n; p++)
            {
                for(int q=0; q<n; q++)
                {
                    if(q) printf(" ");
                    printf("%d",e[p][q]);
                }
            cout<<endl;
            }

        }
        else cout<<"NO"<<endl;
        if(t) cout<<endl;
    }
    return 0;
}