给定一组非负数字,(数字为节点的度),判断该组数字能不能构成图。
Havel-Hakimi定理:
将序列按照从大到小排序之后,从第二个数开始到第一个数的长度+1为止,依次减1。每操作一次,删掉第一个数字。直到整个数组被删完都没有-1出现。则可图。
按照这个定理,我们可做的操作如下:
1.排序
2.先判断第一个数的度是否大于序列-1的长度,如果大于则非图。
如果小于等于,则后面的数依次减1.小于0,则跳出。
3.存图:循环过程中,如果能减1,则第一个数之后的id都指向第一个数。
实例:
3 1 2 1 1
第一次:3 2 1 1 1 删掉3,后面依次减1
得:1 0 0 1
第二次:1 1 0 0.删掉1,后面依次减1
得:0 0 0
所以可图
代码如下:
#include<iostream> #include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> using namespace std; typedef struct { int id; int d; }Arg; Arg arg[10]; int ans[20][20]; int cmp(const void *a,const void *b){ return ((Arg*)b)->d-((Arg*)a)->d; }//从大到小 int main(){ int t,n; cin>>t; while(t--){ cin>>n; memset(ans,0,sizeof(ans));//每一次,将数组置0 for(int i=0;i<n;i++){ cin>>arg[i].d; arg[i].id=i; } int k=0,i,j; while(k<n){ qsort(arg+k,n-k,sizeof(arg[0]),cmp);//第一次排序后,每次删除第一个数排序 if(arg[k].d>n-k-1) break;//如果当前度数已经大于后面的长度,这说明不可能是图 for(i=1;i<=arg[k].d;i++){//次数 if(arg[i+k].d<=0)//小于0跳出 break; arg[i+k].d--; ans[arg[k].id][arg[k+i].id]=ans[arg[k+i].id][arg[k].id]=1;//将后一个数的id,指向前一个数 } if(i<=arg[k].d)//中途跳出 break; k++; } if(k<n)//没有删完,就跳出了 cout<<"NO"<<endl; else { cout<<"YES"<<endl; for(i=0;i<n;i++){ for( j=0;j<n;j++) cout<<ans[i][j]<<" "; cout<<endl; } } } return 0; }