• ZOJ3732 Graph Reconstruction Havel-Hakimi定理


    分析:

    给定一个非负整数序列{dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。

    进一步,若图为简单图,则称此序列可简单图化 (来自百度百科)

    可简单图化的判定可以用Havel-Hakimi定理,然后简述 Havel-Hakimi定理

    Havel-Hakimi定理的过程:

    1,按度数排序。

    2,选取度数最大的点,如果该点度数为0,结束,有解

    3,每次选一个度数最大的点,然后将后面的点的度数依次减1,表示该顶点和相应的顶点有边相连,

       如果有点的度数减到负数,结束,无解。

    4,重复进行步骤1

    然后这个题不只是判定有没有解,还需要判断是否有多解

     “个人认为此题的难点在于多解时要输出两个。在Havel-Hakimi定理的构造过程中,如果把某两个点“互换”,那么就可以构造出多解的,

    那么什么样的两个点才可以互换呢,比如我现在已经排完序,要减的度数序列一直到p,这时,如果p+1的点的度数和p是相同的,

    那么p位置和p+1是可以"互换“的,连这两个点中的哪一个都不会影响结果。”(该段文字引用网上某大牛的想法)

    所以通过判断p和p+1是否相等,就可以判断是否多解

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int N=1e2+5;
    const int INF=0x3f3f3f3f;
    int a[N],d[N],c[N],n;
    bool cmp(int x,int y)
    {
        return c[x]>c[y];
    }
    bool check()
    {
        for(int i=1;i<=n;++i)c[i]=d[i];
        for(int i=1; i<=n; ++i)
        {
            sort(a+1,a+1+n,cmp);
            if(!c[a[1]])break;
            for(int j=2,cnt=1; j<=n&&cnt<=c[a[1]]; ++j,++cnt)
            {
                --c[a[j]];
                if(c[a[j]]<0)return 0;
            }
            c[a[1]]=0;
        }
        return 1;
    }
    struct Edge
    {
        int u,v;
    } x[N*N];
    bool checkmul()
    {
        for(int i=1; i<=n; ++i)c[i]=d[i];
        for(int i=1; i<=n; ++i)
        {
            sort(a+1,a+1+n,cmp);
            if(!c[a[1]])break;
            int k=c[a[1]]+2;
            if(k<=n&&c[a[k]]==c[a[k-1]])return 1;
            for(int j=2,cnt=1; j<=n&&cnt<=c[a[1]]; ++j,++cnt)
                --c[a[j]];
            c[a[1]]=0;
        }
        return 0;
    }
    void print()
    {
        int tot=0;
        for(int i=1; i<=n; ++i)c[i]=d[i];
        for(int i=1; i<=n; ++i)
        {
            sort(a+1,a+1+n,cmp);
            if(!c[a[1]])break;
            for(int j=2,cnt=1; j<=n&&cnt<=c[a[1]]; ++j,++cnt)
            {
                --c[a[j]];
                ++tot;
                x[tot].u=a[1],x[tot].v=a[j];
            }
            c[a[1]]=0;
        }
        for(int i=1; i<=tot; ++i)
        {
            printf("%d",x[i].u);
            if(i<tot)printf(" ");
        }
        printf("
    ");
        for(int i=1; i<=tot; ++i)
        {
            printf("%d",x[i].v);
            if(i<tot)printf(" ");
        }
        printf("
    ");
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            int sum=0;
            for(int i=1; i<=n; ++i)
            {
                scanf("%d",&d[i]);
                sum+=d[i];
                a[i]=i;
            }
            if(!check())
            {
                printf("IMPOSSIBLE
    ");
                continue;
            }
            if(checkmul())
            {
                printf("MULTIPLE
    ");
                printf("%d %d
    ",n,sum/2);
                print();
                printf("%d %d
    ",n,sum/2);
                for(int i=1; i<=n; ++i)c[i]=d[i];
                int tot=0;
                bool flag=1;
                for(int i=1; i<=n; ++i)
                {
                    sort(a+1,a+1+n,cmp);
                    if(!c[a[1]])break;
                    if(flag)
                    {
                        int k=c[a[1]]+2;
                        if(k<=n&&c[a[k]]==c[a[k-1]])
                            swap(a[k],a[k-1]),flag=0;
                    }
                    for(int j=2,cnt=1; j<=n&&cnt<=c[a[1]]; ++j,++cnt)
                    {
                        --c[a[j]];
                        ++tot;
                        x[tot].u=a[1],x[tot].v=a[j];
                    }
                    c[a[1]]=0;
                }
                for(int i=1; i<=tot; ++i)
                {
                    printf("%d",x[i].u);
                    if(i<tot)printf(" ");
                }
                printf("
    ");
                for(int i=1; i<=tot; ++i)
                {
                    printf("%d",x[i].v);
                    if(i<tot)printf(" ");
                }
                printf("
    ");
            }
            else
            {
                printf("UNIQUE
    ");
                printf("%d %d
    ",n,sum/2);
                print();
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    可恶的0x1A
    求关注 wcf bindipendpointdelegate 端口限制的功能
    2015 UESTC Training for Data Structures
    Codeforces Round #298 (Div. 2)
    利用rawcap抓包(自己发给自己的包裹)
    PYTHON POST练手
    CentOS安装Nginx 实现HTTP代理
    how to make vim show ^M and substitute it
    Oracle SQL Developer: cannot find a j2se sdk
    Codeforces Round #282 (Div. 2)
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5326057.html
Copyright © 2020-2023  润新知