poj 1659 Frogs' Neighborhood( 青蛙的邻居)

Frogs' Neighborhood
Time Limit: 5000MS   Memory Limit: 10000K
Total Submissions: 9639   Accepted: 4051   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.对最大度数后面的d1个度数各减1后,出现了负数
#include<queue>
#include<stack>
#include<math.h>
#include<stdio.h>
#include<numeric>//STL数值算法头文件
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<functional>//模板类头文件
using namespace std;

#define N 100
struct vertex
{
    int degree;//顶点的度
    int index;//顶点的序号
} v[N];
int cmp(const void *a,const void *b)
{
    return ((vertex*)b)->degree-((vertex*)a)->degree;
}

int main()
{
    int r,k,p,q;//循环变量
    int i,j;//顶点序号(用于确定图中边的两个顶点)
    int d1;//对剩下的序列排序后第1个顶点(度数最大的顶点)的度数
    int T,n;//测试数据个数,湖泊个数
    int edge[N][N],flag;//邻接矩阵,是否存在合理乡里关系的标志
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(i=0; i<n; i++)
        {
            scanf("%d",&v[i].degree);
            v[i].index=i;
        }
        memset(edge,0,sizeof(edge));
        flag=1;
        for(k=0; k<n&&flag; k++)
        {
            //对v数组后n-k个元素按非递增顺序排序
            qsort(v+k,n-k,sizeof(vertex),cmp);//各参数:1 待排序数组首地址 2 数组中待排序元素数量 3 各元素的占用空间大小 4 指向函数的指针
            i=v[k].index;//第k个顶点的序号
            d1=v[k].degree;
            if(d1>n-k-1) flag=0;
            for(r=1; r<=d1&&flag; r++)
            {
                j=v[k+r].index;//后边d1个顶点中每个顶点的序号
                if(v[k+r].degree<=0) flag=0;
                v[k+r].degree--;
                edge[i][j]=edge[j][i]=1;
            }
        }
        if(flag)
        {
            puts("YES");
            for(p=0; p<n; p++)
            {
                for(q=0; q<n; q++)
                {
                    if(q) printf(" ");
                    printf("%d",edge[p][q]);
                }
                puts(" ");//换行
            }
        }
        else printf("NO\n");
        if(T) puts(" ");
    }
    return 0;
}


//可以根据Havel-hakimi定理推一遍
//把i和d1输出,分别代表序号和度
//每组i和d1如果满足条件,再把j输出,j代表d1后面每个顶点的序号
//1
//7
//4 3 1 5 4 2 1
//3 5
//4
//0 
//1 
//5
//6
//0 3
//4
//1
//2
//4 2
//5
//1
//1 0    不满足第二层for循环的条件则只输出i和d1
//2 0
//6 0
//5 0
posted @ 2017-01-11 21:25  xushukui  阅读(194)  评论(0)    收藏  举报