Havel-Hakimi定理的方法来构图

给定一组非负数字,(数字为节点的度),判断该组数字能不能构成图。

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;
} 

 

posted @ 2018-11-10 15:59  一头  阅读(501)  评论(0编辑  收藏  举报