【图论】度序列可简单图化判断

\(Havel-Hakimi\) 定理

学习资料: makenothing博客

判断给定度序列是否可简单图化

可简单图化:一个由非负整数组成的有限序列如果是某个无向图的序列,则称该序列是可简单图化的。

定理描述:

由非负整数组成的有限非递增序列, \(S=\{d_1,d_2,...,d_n\}\) , 当且仅当 \(S_1=\{d_2-1,d_3-1,...,d_{d_1+1} -1,d_{d_1+2},...,d_n\}\) 也是可图的, 也就是说, 序列 \(S_1\) 也是由非负整数组成的有限非递增序列。

判定过程:

  • 对当前序列 \(S\) 排序, 使其呈递减,若首元素为0, 则判断该序列可简单图化, 否则继续下一步。
  • 删除序列首元素 \(d_1\) ,并使序列之后的 \(d_1\) 个数的值均减 \(1\), 若出现了负数, 则该可判断该序列是不可简单图化, 否则,继续上一步。

例题:

P3104 [USACO14MAR]Counting Friends G

一句话题意: 给 \(n+1\) 个数,问哪些数满足删除它之后所剩下的长度为 \(n\) 的序列可简单图化, 输出这些数的下标。其中 \(1\le n\le500\) .

\(code:\)

//#pragma GCC optimize("-O2")
#include<bits/stdc++.h>
#define reg register
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int maxn=2e5+5;

struct A{
    int v,id;
}a[maxn];

int p[maxn],t[maxn],n;
bool check()
{
    int x,st=1,l1,l2,r1,r2,cnt;
    while(p[st]>0)
    {
        x=p[st];
        for(int i=st+1;i<=st+x;i++)p[i]--;
        if(p[st+x]<0)return 0;
        //归并排序O(n)替换快排O(nlogn)
        l1=st+1;l2=st+x+1;cnt=0;
        while(l1<=st+x||l2<=n)
        {
            if(l1<=st+x&&p[l1]>=p[l2]||l2>n)t[++cnt]=p[l1++];
            else t[++cnt]=p[l2++];
        }
        for(int i=1;i<=cnt;i++)p[st+i]=t[i];st++;
//        sort(p+st,p+1+n,greater<int>());
    }
    return 1;
}
vector<int>ans;
int main()
{
    scanf("%d",&n);
    for(int i=1,v;i<=n+1;i++)
    {
        scanf("%d",&a[i].v);a[i].id=i;
    }
    sort(a+1,a+1+n+1,[](A a1,A a2)->bool{return a1.v>a2.v;});
    for(int i=1;i<=n+1;i++)
    {
        for(int j=1,cnt=0;j<=n+1;j++)
        {
            if(i==j)continue;
            p[++cnt]=a[j].v;
        }
        if(check())ans.push_back(a[i].id);
    }
    sort(ans.begin(),ans.end());
    printf("%d\n",ans.size());
    for(int u:ans)printf("%d\n",u);
}
posted @ 2020-04-28 00:39  草丛怪  阅读(8237)  评论(0编辑  收藏  举报