1. 程式人生 > >ZOJ 3732 可圖性判定--Havel-Hakimi定理

ZOJ 3732 可圖性判定--Havel-Hakimi定理

題意:給定n個點度數,問是否可以構造一個簡單圖。

思路:Havel-Hakimi定理 :

1.將度數從小到大排序

2.用第一個向後面連續d[1]個點連邊,若點數不夠則不能構造

3.若點數夠,則將每個點度數減1,若出現負值,則不能構造,

4.去掉該點返回步驟一,直到集合中沒有點。

對於多個圖,只需要判定i+d[i]和i+d[i]+1這兩個點度數是否一致,

若一致就交換。即可達到不同圖的目標。

#include<bits/stdc++.h>
#define fir first
#define sec second
using namespace std;
const int N=110;
int deg[N];
int n;
vector<int> u[2], v[2];

bool havel(){
    int tmp[N];
    for(int i=1; i<=n; i++)
        tmp[i]=deg[i];
    for(int i=1; i<n; i++){
        sort(tmp+i, tmp+1+n, greater<int>());
        if(tmp[i] > n-i) return false;
        for(int j=1; j<=tmp[i]; j++){
            tmp[i+j]--;
            if(tmp[i+j]<0) return false;
        }
    }
    return true;
}

bool cmp(pair<int, int> a, pair<int, int> b){
    return a.fir>b.fir;
}

bool solve(){
    pair<int,int> p[N];
    for(int i=1; i<=n; i++)
        p[i].fir=deg[i], p[i].sec=i;
    bool ok=false;
    for(int i=1; i<=n; i++){
        sort(p+i, p+1+n, cmp);

        if(i+p[i].fir<n && p[i+p[i].fir].fir==p[i+p[i].fir+1].fir && p[i+p[i].fir].fir!=0){
            ok=true;
        }
        for(int j=1; j<=p[i].fir; j++){
            u[0].push_back(p[i].sec);
            v[0].push_back(p[i+j].sec);
            p[i+j].fir--;
        }

    }

    if(!ok) return true;

    for(int i=1; i<=n; i++)
        p[i].fir=deg[i], p[i].sec=i;

    for(int i=1; i<=n; i++){
        sort(p+i, p+1+n, cmp);

        if(i+p[i].fir<n && p[i+p[i].fir].fir==p[i+p[i].fir+1].fir && p[i+p[i].fir].fir!=0){
            swap(p[i+p[i].fir].sec, p[i+p[i].fir+1].sec);
        }

        for(int j=1; j<=p[i].fir; j++){
            u[1].push_back(p[i].sec);
            v[1].push_back(p[i+j].sec);
            p[i+j].fir--;
        }

    }

    return false;
}

int main(){
    while(~scanf("%d", &n)){
        u[0].clear(); u[1].clear();
        v[0].clear(); v[1].clear();
        for(int i=1; i<=n; i++)
            scanf("%d", deg+i);

        if(!havel()){
            printf("IMPOSSIBLE\n");
        }
        else{

                if(solve()){
                    printf("UNIQUE\n");
                    printf("%d %d\n", n, u[0].size());
                    if(u[0].size()) printf("%d", u[0][0]);
                    for(int i=1; i<u[0].size(); i++)
                        printf(" %d", u[0][i]);
                    puts("");
                    if(v[0].size()) printf("%d", v[0][0]);
                    for(int i=1; i<v[0].size(); i++)
                        printf(" %d", v[0][i]);
                    puts("");
                }
                else{
                    printf("MULTIPLE\n");
                    printf("%d %d\n", n, u[0].size());
                    if(u[0].size()) printf("%d", u[0][0]);
                    for(int i=1; i<u[0].size(); i++)
                        printf(" %d", u[0][i]);
                    puts("");
                    if(v[0].size()) printf("%d", v[0][0]);
                    for(int i=1; i<v[0].size(); i++)
                        printf(" %d", v[0][i]);
                    puts("");

                    printf("%d %d\n", n, u[1].size());
                    if(u[1].size()) printf("%d", u[1][0]);
                    for(int i=1; i<u[1].size(); i++)
                        printf(" %d", u[1][i]);
                    puts("");
                    if(v[1].size()) printf("%d", v[1][0]);
                    for(int i=1; i<v[1].size(); i++)
                        printf(" %d", v[1][i]);
                    puts("");
                    }

            }

    }

    return 0;
}