zoukankan      html  css  js  c++  java
  • BZOJ4316 : 小C的独立集

    取一棵原图的DFS生成树,那么因为是仙人掌,所以每条树边最多只会属于一个环。

    设$f[i][j][k]$表示考虑$i$的子树,$i$点选择情况为$j$,$i$到父亲对应的环边底部的点选择情况为$k$时的最大独立集。

    然后直接树形DP即可,在每个环的底部以及顶部的两条边处特殊处理转移。

    时间复杂度$O(n+m)$。

    #include<cstdio>
    #define rep(i) for(int i=0;i<2;i++)
    const int N=50010,M=60010;
    int n,m,i,x,y,g[N],v[M<<1],nxt[M<<1],ed,ans;
    int vis[N],dfn,p[N],f[N][2][2],h[2][2];bool top[N],bot[N];
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    inline void up(int&a,int b){a<b?(a=b):0;}
    void dfs(int x,int y){
      vis[x]=++dfn;p[x]=y;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y&&vis[v[i]])bot[x]=1;
      f[x][1][bot[x]]=1;
      for(int i=g[x];i;i=nxt[i]){
        int u=v[i];
        if(u==y)continue;
        if(!vis[u]){
          dfs(u,x);
          rep(j)rep(k)h[j][k]=0;
          rep(j)rep(k)rep(a)rep(b){
            if(j&&a)continue;
            if(top[u]&&j&&b)continue;
            up(h[j][k|(b&!top[u])],f[x][j][k]+f[u][a][b]);
          }
          rep(j)rep(k)f[x][j][k]=h[j][k];
        }else if(vis[u]<vis[x]){
          int o=x;
          while(p[o]!=u)o=p[o];
          top[o]=1;
        }
      }
    }
    int main(){
      read(n),read(m);
      while(m--)read(x),read(y),add(x,y),add(y,x);
      for(i=1;i<=n;i++)if(!vis[i]){
        dfs(i,0);
        x=0;
        rep(j)rep(k)up(x,f[i][j][k]);
        ans+=x;
      }
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    python学习笔记-4-列表和元组
    迭代器 生成器, 可迭代对象以及应用场景
    mysql的创创建用户阶段 开启客户端登录和授权阶段
    初识mysql数据库
    拆目录
    日志编码
    数据库mysql的安装.启动和基础配置------windows版本
    协程
    线程锁 死锁现象 递归锁 信号量 条件定时器 队列 线程池
    网络线程
  • 原文地址:https://www.cnblogs.com/clrs97/p/7518696.html
Copyright © 2011-2022 走看看