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\n",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
*/

 

posted @ 2017-09-22 21:35  meekyan  阅读(338)  评论(0编辑  收藏  举报