[SDOI2019]热闹又尴尬的聚会(图论+set+构造)

据说原数据可以让复杂度不满的暴力O(Tn^2)过掉……O(Tn^2)方法类似于codeforces一场div2的E题

有一种比较好的方法:每次找出原图G中度最小的点加入q,然后将相邻的点加入新图G'。这显然能够得到一个最大的独立集。而p可以在维护度最小的点最大这一过程中,把G的所有点加入集合p。因为set带一个log,所以复杂度为O(Tmlogn)。

证明:满足(p+1)(q+1)>n即可。删除的q节点中d的度数和满足Σ(d[i]+1)=n,其中i∈q,然后max{d[i]}q>=n,于是(max{d[i]}+1)q>n,而p>=max{d[i]},所以命题成立。

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+7;
int n,m,n1,n2,len,deg[N],vis[N],s1[N],s2[N],b[N];
vector<int>G[N];
struct node{int u,d;}a[N];
bool operator<(node a,node b){return a.d==b.d?a.u<b.u:a.d<b.d;}
typedef set<node>::iterator iter;
set<node>S;
inline int read()
{
    int x=0,w=0;
    char ch=0;
    while(!isdigit(ch))w|=ch=='-',ch=getchar();
    while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return w?-x:x;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        n=read(),m=read();
        n1=n2=len=0;
        for(int i=1;i<=n;i++)G[i].clear(),deg[i]=vis[i]=0,a[i]=(node){i,0};
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            G[x].push_back(y),G[y].push_back(x);
            deg[x]++,deg[y]++,a[x].d++,a[y].d++;
        }
        for(int i=1;i<=n;i++)S.insert(a[i]);
        int mxd=-1,mx=0;
        while(!S.empty())
        {
            int u=(*S.begin()).u;
            if(deg[u]>mxd)mxd=deg[u],mx=len;
            S.erase(S.begin());
            b[++len]=u,s2[++n2]=u,vis[u]=1;
            for(int i=0;i<G[u].size();i++)
            {
                int v=G[u][i];
                iter it=S.find((node){v,deg[v]});
                if(it==S.end())continue;
                S.erase(it),b[++len]=v;
                for(int j=0;j<G[v].size();j++)
                {
                    int t=G[v][j];
                    it=S.find((node){t,deg[t]});
                    if(it==S.end())continue;
                    S.erase(it),S.insert((node){t,--deg[t]});
                }
            }
        }
        for(int i=mx+1;i<=len;i++)s1[++n1]=b[i];
        printf("%d",n1);for(int i=1;i<=n1;i++)printf(" %d",s1[i]);
        printf("\n%d",n2);for(int i=1;i<=n2;i++)printf(" %d",s2[i]);
        puts("");
    }
}
View Code

 

posted @ 2019-05-09 13:06  hfctf0210  阅读(193)  评论(0编辑  收藏  举报