zoukankan      html  css  js  c++  java
  • BZOJ 4316: 小C的独立集 解题报告

    4316: 小C的独立集

    Description

    图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨。

    这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多。

    小D虽然图论很弱,但是也知道无向图最大独立集是npc,但是小C很仁慈的给了一个很有特点的图: 图中任何一条边属于且仅属于一个简单环,图中没有重边和自环。小C说这样就会比较水了。

    小D觉得这个题目很有趣,就交给你了,相信你一定可以解出来的。

    Input

    第一行,两个数(n)(m),表示图的点数和边数。

    (2sim m+1)行,每行两个数(x)(y),表示(x)(y)之间有一条无向边。

    Output

    输出这个图的最大独立集。

    HINT

    (100\%) (nle 50000,mle 60000)


    不用建圆方树的仙人掌。

    最大独立集:选出最大的点集,使得两两没有边连接。

    对普通树边按普通的(dp)即可

    对环上的点,把环的头拽出来,然后从它屁股dp上去就行了


    Code:

    #include <cstdio>
    const int N=6e4+10;
    int head[N],to[N<<1],Next[N<<1],cnt;
    void add(int u,int v)
    {
        to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
    }
    int min(int x,int y){return x<y?x:y;}
    int max(int x,int y){return x>y?x:y;}
    const int inf=0x3f3f3f3f;
    int n,m,dp[N][2],dfn[N],low[N],dfsclock,fa[N];
    void cal(int rt,int now)
    {
        int t=now,s0=0,s1=0;
        while(now!=rt)
        {
            int tmp=s0;
            s0=max(s0,s1)+dp[now][0];
            s1=tmp+max(dp[now][1],dp[now][0]);
            now=fa[now];
        }
        dp[rt][0]+=max(s0,s1);
        s0=-inf,s1=0,now=t;
        while(now!=rt)
        {
            int tmp=s0;
            s0=max(s0,s1)+dp[now][0];
            s1=tmp+max(dp[now][1],dp[now][0]);
            now=fa[now];
        }
        dp[rt][1]+=s0;
    }
    void dfs(int now)
    {
        dp[now][1]=1;
        dfn[now]=low[now]=++dfsclock;
        for(int v,i=head[now];i;i=Next[i])
            if((v=to[i])!=fa[now])
            {
                if(!dfn[v]) fa[v]=now,dfs(v),low[now]=min(low[now],low[v]);
                else low[now]=min(low[now],dfn[v]);
                if(dfn[now]<low[v])//正常树边
                    dp[now][0]+=max(dp[v][0],dp[v][1]),dp[now][1]+=dp[v][0];
            }
        for(int v,i=head[now];i;i=Next[i])
            if(fa[v=to[i]]!=now&&dfn[v]>dfn[now])
                cal(now,v);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int u,v,i=1;i<=m;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);
        dfs(1);
        printf("%d
    ",max(dp[1][0],dp[1][1]));
        return 0;
    }
    

    2018.12.24

  • 相关阅读:
    Spring IOC实现原理,源码深度剖析!
    MYSQL配置参数优化详解
    MYSQL 索引优化全攻略
    MySQL性能优化实战
    最强MySQL MVCC实现原理
    redis集群代建
    redis分布式锁
    mysql 的语句的执行顺序
    Rockey pushConsumer 和 pullConsumer 的区别
    RockeyMQ消息处理
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10171246.html
Copyright © 2011-2022 走看看