HavelHakimi定理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qiaojun1234567/article/details/23028909

1、HavelHakimi定理简介:

该定理的目的是判断某一个非零序列是否可图。什么意思呢?我们知道对于一个图,它的每个顶点都是有度数的,有几条边与某顶点相连,那么该顶点的度数就是几。所以对于一个图来讲我们可以写出所有顶点的度数。然后反过来,给你一个序列,序列的值代表某个顶点度数。问是否存在一个图,它的度数序列是这样的?

2、实现过程:

 首先把度数序列从大到小排列,然后删除第最大的度数di(表示在数组的i号位置,值为d),然后从第i+1个数起到i+di所有的在这区间的度数均减小1,一直重复直到度数序列的值都为0;

举个例子:

序列 :4 3 1 5 4 2 1

1从大到小排列:5 4 4 3 2 11

2删除最大的数 5后得:4 4 3 2 1 1

3把前面的5个数 减小1得:3 3 2 1 0 1

1从大到小排列:3 3 2 1 1 0

2删除最大的数 3后得:3 2 1 1 0

3把前面的3个数 减小1得:2 1 0 1 0

1从大到小排列2 1 1 0 0

2删除最大的数 2后得:1 1 0 0

3把前面的2个数 减小1得0 0 0 0

结束

模板:

bool HavelHakimi(int n)
{
    for(i = 0;i < n-1;++i)
    {
        sort(arr+i,arr+n,greater<int>());
        if(arr[i] + i >= n) return false;
        /*
        前面的i个顶点的度数已经足够了,现在剩余n-i个顶点,
        现在从这n-i个顶点里面找出一个顶点它的度数为arr[i],
        arr[i]就代表与这个顶点相连的顶点个数,必然有arr[i]<n-i成立。
        */
        for(j = i+1;j <= arr[i]+1;j++)
        {
            arr[j]--;
            if(arr[j] < 0) return false;
        }
    }
    if(arr[n-1] != 0) return false;
    return true;
}

假如过程中出现了-1那么就不可图。另外,我们有必要对其进行编号(每个顶点的编号),每个编号是固定不变的。例如上面的我们的度数序列 4 3 1 5 4 2 1,我们知道它是7个顶点的度数,我们必须明确某个度数是哪个顶点,并且以后的计算中保持不变。一般初始化的时候序列的第一个代表0号顶点,第二个度数代表1号结点,以此类推。。

题目poj1659:Frogs'Neighborhood

题目的意思就是给你每个顶点的度数,问一下这个顶点序列是否可图?如果可图,就要画出图的邻接矩阵,这就要求你保存每个地度数所属于的顶点

AC代码:

#include <iostream>
#include <functional>
#include <string.h>
#include <algorithm>
using namespace std;
int arr[20][20];
struct MAT
{
    int num;//该度数代表的顶点标号,一经确认,不在改变!
    int value;//顶点的度数
}mat[20];
int cmp(MAT a,MAT b)
{
    return a.value>b.value;
}
bool love_zy(int n)
{
    int i,j;
    for(i=0;i<n-1;i++)
    {
        sort(mat+i,mat+n,cmp);
        if(mat[i].value+i>=n) return false;
        for(j=i+1;j<=mat[i].value+i;j++)
        {
            mat[j].value--;
            if(mat[j].value <0)return false;
            arr[mat[i].num][mat[j].num] = 1;
            arr[mat[j].num][mat[i].num] = 1;
        }
    }
    if(mat[n-1].value!=0) return false;
    return true;
}
void print(int n)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
            cout <<arr[i][j]<<" ";
        cout <<endl;
    }
    cout <<endl;
}
int main()
{
    int T,N,i,j;
    cin>>T;
    while(T--)
    {
       cin>>N;
       memset(arr,0,sizeof(arr));
       for(i=0;i<N;i++)
       {
           cin>>mat[i].value;
           mat[i].num = i;
       }
       if(love_zy(N))
       {
           cout <<"YES"<<endl;
           print(N);
       }
       else
        cout <<"NO"<<endl<<endl;
    }
    return 0;
}

参考:http://sbp810050504.blog.51cto.com/2799422/883904

 

 

 

猜你喜欢

转载自blog.csdn.net/qiaojun1234567/article/details/23028909
今日推荐