zoukankan      html  css  js  c++  java
  • bzoj 3579: 破冰派对

    题意:

    给你一个图,问你有多少个方案把他分成连个新的图。使得一个图是一个团,另外一个是独立集

    一些闲话:

    以前做过一次这个题..当时听说爆搜可以过,就无脑莽过去了..

    也没有思考为什么爆搜能过,或者有没有非爆搜的方法..

    其实这题是有非爆搜,并且是线性的做法

    题解:

    先考虑这么一个事实:加入我们得到了一个合法解,那么剩下的合法解肯定可以通过下面的调整得到:

    1.从团里面丢一个点到独立集里面

    2.从独立集里面丢一个点到团里面

    3.独立集和团交换一个点

    显然,所有操作都不可能设计独立集/团里面的两个点,这样就使问题好办了许多

    考虑怎么得到一个合法解

    一般来说,我们可以贪心来做,按度数排一个序,然后从大到小看,能放到团里面就放到团里面,否则丢到独立集里面

    最后看一下独立集是否合法..

    尝试证明这个贪心的正确性,我们只需要证明只要有解,这样一定可以找出来即可

    先假设i,j,按度数排序后i在j前面,如果存在一个方案是把i放到独立集里面,而把j放到团里面,不难得到i和j是等价的,因为j要和所有i连出的边连边

    因此这两个点谁放哪里都一样

    于是我们就得到了一个合法解

    定义可以自由转化阵营的是自由点,否则是非自由点

    两个都是自由点的方案很好算,两个都是非自由点的可以发现是没有的

    那么各有一般怎么算..其实也是暴力就好了,看看唯一影响这个点非自由的是不是自由点就好了

    这个部分可以写成O(m)

    至于排序,可以用桶排来解决,因此总复杂度就是O(n+m)

    但是因为这个题数据很不好造..因此爆搜什么的很难卡..n,m如果同阶,显然团的个数也会很少,因此,就算暴力一点写成O(n^2+m)也应该可以过n,m同阶的点

    然后就没什么了

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long LL;
    const int N=1005;
    int T;
    int n,m;
    struct qq
    {
        int x,y,last;
    }e[N*N*2];int num,last[N];
    void init (int x,int y)
    {
        e[++num].x=x;e[num].y=y;
        e[num].last=last[x];
        last[x]=num;
    }
    int du[N];
    int id[N];
    bool cmp (int x,int y)  {return du[x]>du[y];}
    bool in[N];
    int o[N];
    int read ()
    {
        char ch=getchar();int x=0;
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    int main()
    {
        T=read();
        while (T--)
        {
            num=0;memset(last,-1,sizeof(last));
            //scanf("%d%d",&n,&m);
            n=read();m=read();
            for (int u=1;u<=n;u++) du[u]=0;
            for (int u=1;u<=m;u++)
            {
                int x,y;
                //scanf("%d%d",&x,&y);
                x=read();y=read();
                init(x,y);init(y,x);
                du[x]++;du[y]++;
            }
            for (int u=1;u<=n;u++) id[u]=u,in[u]=false;
            sort(id+1,id+1+n,cmp);
            int cnt=0;//有多少个
            for (int u=1;u<=n;u++)
            {
                int x=id[u];int sum=0;
                for (int i=last[x];i!=-1;i=e[i].last) sum=sum+in[e[i].y];
                if (sum==cnt)   {in[x]=true;cnt++;}
            }
            bool tf=true;
            for (int u=1;u<=num;u++) if (in[e[u].x]==false&&in[e[u].y]==false) {tf=false;break;}
            if (tf==false) {printf("0
    ");continue;}
            int cnt1=0,cnt2=0;
            for (int u=1;u<=n;u++)
            {
                o[u]=0;
                for (int i=last[u];i!=-1;i=e[i].last)   o[u]=o[u]+(in[u]!=in[e[i].y]);
                if (in[u]==true&&o[u]==0) cnt1++;
                if (in[u]==false&&o[u]==cnt) cnt2++;
            }
            int ans=(cnt!=n);//printf("%d %d
    ",ans,n);
            ans=ans+(cnt1+1)*(cnt2+1)-1;
             
            if (cnt==1&&cnt1==1) ans--;
        //  printf("%d %d %d %d
    ",ans,cnt1,cnt2,cnt);
            int tot=0;
            for (int u=1;u<=n;u++)  if (in[u]&&du[u]==cnt-1) tot++;
            for (int u=1;u<=n;u++) if (in[u]==false&&du[u]==cnt-1)
            {
                int now=0;
                for (int i=last[u];i!=-1;i=e[i].last)
                {
                    int y=e[i].y;
                    if (in[y]&&du[y]==cnt-1) now++;
                }
            //  if (now>tot) printf("FUCK!
    ");
                ans=ans+tot-now;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Python补充06 Python之道
    java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括InputStream)
    java io系列01之 "目录"
    字符编码(ASCII,Unicode和UTF-8) 和 大小端
    Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(7) TimeZone
    Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(6) Locale
    Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(5) SimpleDateFormat
    Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(4) DateFormat
    Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(3) Date
    Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(2) 自己封装的Calendar接口
  • 原文地址:https://www.cnblogs.com/Als123/p/11077298.html
Copyright © 2011-2022 走看看