Havel-Hakimi定理(判断一个序列是否可图)->POJ1659

Havel-Hakimi定理(判断一个序列是否可图)->POJ1659


给定一个非负整数序列{dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。进一步,若图为简单图,则称此序列可简单图化
至于能不能根据这个序列构造一个图,就需要根据Havel-Hakimi定理中的方法来构图。


可图化的判定:

d1+d2+……dn=0(mod 2)。关于具体图的构造,我们可以简单地把奇数度的点配对,剩下的全部搞成自环。

可简单图化的判定(Havel定理):

把序列排成不增序,即d1>=d2>=……>=dn,则d可简单图化当且仅当d’={d2-1,d3-1,……d(d1+1)-1, d(d1+2),d(d1+3),……dn}可简单图化。简单的说,把d排序后,找出度最大的点(设度为d1),把它与度次大的d1个点之间连边,然后这个点就可以不管了,一直继续这个过程,直到建出完整的图,或出现负度等明显不合理的情况。

当然构图过程中也会出现不合理的情况。
1:某次对剩下序列排序后,最大的度数比剩下的顶点数还要多。
2:度数-1后,出现负数。
上面两种情况都是无法构成图的。


POJ1659
题意:

给一个度的序列,要求判断是否能构图,如果能就输出图。

题解:

Havel-Hakimi定理的简单应用

每次把node[i]之后的区间排序,再把其后的连续node[i].neighbor个节点的度都减一,直到出现矛盾或完全判断完成。

代码:

#include 
#include 
#include 
#include 
using namespace std;

const int NN=12;

int n;
struct node{
    int id,nb;
}frog[NN];
bool comp(const struct node &a,const struct node &b){
    return a.nb>b.nb;
}
bool build()
{
    int link[NN][NN];
    memset(link,0,sizeof(link));
    for (int i=0; iif (frog[i].nb>n-i-1) return false;
        for (int j=i+1; j<=i+frog[i].nb; j++)
        {
            if (!frog[j].nb) return false;
            frog[j].nb--;
            link[frog[i].id][frog[j].id]=1;
            link[frog[j].id][frog[i].id]=1;
        }
        frog[i].nb=0;
    }
    printf("YES\n");
    for (int i=0; iprintf("\n"))
      for (int j=0; jprintf("%d ",link[i][j]);
    return true;
}

int main()
{
    int cas;
    scanf("%d",&cas);
    while (cas--)
    {
        scanf("%d",&n);
        for (int i=0; ifor (int i=0; iscanf("%d",&frog[i].nb);
        }
        if (!build()) printf("NO\n");
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(图论,POJ)