Frogs' Neighborhood
Time Limit: 5000MS | Memory Limit: 10000K | |||
Total Submissions: 9639 | Accepted: 4051 | Special Judge |
Description
未名湖附近共有N个大小湖泊L1, L2, ..., Ln(其中包括未名湖),每个湖泊Li里住着一只青蛙Fi(1 ≤ i ≤ N)。如果湖泊Li和Lj之间有水路相连,则青蛙Fi和Fj互称为邻居。现在已知每只青蛙的邻居数目x1, x2, ..., xn,请你给出每两个湖泊之间的相连关系。
Input
第一行是测试数据的组数T(0 ≤ T ≤ 20)。每组数据包括两行,第一行是整数N(2 < N < 10),第二行是N个整数,x1, x2,..., 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 "); 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