BZOJ 4316: 小C的独立集 仙人掌 + 树形DP
Posted Meek
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4316: 小C的独立集 仙人掌 + 树形DP相关的知识,希望对你有一定的参考价值。
4316: 小C的独立集
Time Limit: 10 Sec Memory Limit: 128 MBDescription
图论小王子小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
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 */
以上是关于BZOJ 4316: 小C的独立集 仙人掌 + 树形DP的主要内容,如果未能解决你的问题,请参考以下文章