zoukankan      html  css  js  c++  java
  • BZOJ 4316: 小C的独立集 仙人掌 + 树形DP

    4316: 小C的独立集

    Time Limit: 10 Sec  Memory Limit: 128 MB

    Description

    图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨。
    这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多。
    小D虽然图论很弱,但是也知道无向图最大独立集是npc,但是小C很仁慈的给了一个很有特点的图: 图中任何一条边属于且仅属于一个简单环,图中没有重边和自环。小C说这样就会比较水了。
    小D觉得这个题目很有趣,就交给你了,相信你一定可以解出来的。

    Input

    第一行,两个数n, m,表示图的点数和边数。
    第二~m+1行,每行两个数x,y,表示x与y之间有一条无向边。

    Output

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

    Sample Input

    5 6
    1 2
    2 3
    3 1
    3 4
    4 5
    3 5

    Sample Output

    2

    HINT

    100% n <=50000, m<=60000

     

    Source

    题解:

       这个图是仙人掌图啊

      对于一个环就直接 另外 DP就好了

      环与环相邻,逐个求解不受影响啊

      设定dp[i][0/1] 表示当前i为根节点的且选与不选的状态下 其子树 的 最大可选节点数

    #include <bits/stdc++.h>
    inline long long read(){long long x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    using namespace std;
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define MP make_pair
    typedef long long LL;
    typedef unsigned long long ULL;
    const long long INF = 1e18+1LL;
    const double pi = acos(-1.0);
    const int N = 2e5 + 10, M = 502, inf = 1e9;
    
    vector<int > G[N];
    int dp[N][2],n,m,fa[N];
    int dep[N];
    
    void gao(int x,int y) {
        //cout<<x<<" " <<y<<endl;
        int last0 = 0, last1 = 0;
        for(int i = x; i != y; i = fa[i]) {
            int tmp = last0;
            last0 = max(last0,last1) + dp[i][0];
            last1 = tmp + dp[i][1];
        }
        dp[y][0] += max(last1,last0);
    
       // int fuck =  max(last0,last1);
        last0 = -inf, last1 = 0;
        for(int i = x; i != y; i = fa[i]) {
            int tmp = last0;
            last0 = max(last0,last1) + dp[i][0];
            last1 = tmp + dp[i][1];
        }
    
       // fuck = max(max(last0,last1),fuck);
    
        //dp[y][0] += fuck;
        dp[y][1] += last0;
    }
    
    void dfs(int u,int f) {
        dep[u] = dep[f] + 1;
        fa[u] = f;
        dp[u][1] = 1;
      //  cout<<u<<" "<<f<<endl;
        for(int i = 0; i < G[u].size(); ++i) {
            int to = G[u][i];
            if(to == f) continue;
            if(!dep[to]) {dfs(to,u);}
        }
        for(int i = 0; i < G[u].size(); ++i) {
            int to = G[u][i];
            if(to == f) continue;
            if(dep[to] > dep[u] && fa[to] != u) {///montherfuck
                gao(to,u);
            }
        }
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= m; ++i) {
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1,0);
        printf("%d
    ",max(dp[1][0],dp[1][1]));
        return 0;
    }
    /*
    17 20
    1 2
    2 3
    3 4
    4 5
    5 2
    2 6
    6 7
    7 8
    8 9
    9 10
    10 11
    11 12
    12 6
    6 13
    13 14
    14 15
    15 16
    16 17
    17 13
    13 1
    */
  • 相关阅读:
    随机数
    质数
    猜数
    失败
    判断质数
    2019.7.21记录
    9*9乘法表
    小人
    奔跑的字母

  • 原文地址:https://www.cnblogs.com/zxhl/p/7577258.html
Copyright © 2011-2022 走看看