Time Limit: 5000MS | Memory Limit: 10000K | |||
Total Submissions: 9293 | Accepted: 3921 | 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,判定过程:
(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; }