树的最大独立集定义为:在无根树上找出最多的不相连的点。
那么,怎么求最大独立集呢,用递归的思想构造动态规划。
设dp(i)表示以i为根的树所拥有的最大独立集。
那么我们思考转移,把问题变小发现,膜法转移,为什么呢,因为我们知道子问题,他的子树所拥有的最大独立集,却不能表示原问题的最大独立集。
因为这不能单纯相加,所以我们思考,还有什么可以影响决策,我们发现,可以影响决策的还有一个东西,那就是是否在独立集内部。
所以,dp(i,0)表示以i为根节点,并且i不在集合内部的最大独立集,如果i不在集合内部,那么他的子节点一定在或不在集合内部。
所以dp(i,0)=∑max(dp(i的子节点,1),dp(i的子节点,0));
dp(i,1)表示以i为根节点,并且i在集合内部的最大独立集,那么,以i为根的子节点一定不在集合内部。
所以dp(i,1)=∑dp(i的子节点,0)。
所以dp(i,1/0)=max(∑max(dp(i的子节点,1),dp(i的子节点,0)),∑dp(i的子节点,0));
附上代码
int dp(int u,int fa) { f[u][0]=1; f[u][1]=0; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v==fa)continue; dp(v,u); f[u][0]+=f[v][1]; f[u][1]+=max(f[v][0],f[v][1]); } return max(f[u][0],f[u][1]); }
现在,来看一道题目
LazyChild 黑 OJ(blackoj.pas/c/cpp)
LazyChild 开了一家“善良 OJ”。但大多数人都不知道,这其实是家黑 OJ。亲爱的同学,请
不要惊讶,古时候有黑店,现代为什么不能有黑 OJ 呢?每 AC 一道题,网站便会自动在电
脑上安装一种木马。LazyChild 通过窃取信息获取收益(如网游帐号、OI 资料、YuanY 和
TT 的照片等等)。
作为一名资深黑客,老 Z 某日突然发现,“善良 OJ”上的木马,自己电脑上都没有。这可十
分让他过意不去。老 Z 决定通过多 A 题,来丰富自己电脑的病毒库。
经过调查,老 Z 发现,很多木马是不能共存的。比如“和谐”木马与“团结”木马,两者
只能任选其一。然而,老 Z 是个完美主义者,他想要自己的病毒库尽可能充实。
老 Z 不懈的追求最终感动了上天。天上的神仙(半仙?)“牛人雨”给这个问题稍稍降低了
一点难度。神仙规定,对于 n 种木马,有且仅有(n-1)对不能共存,并且对于每种木马,都存
在至少一个木马与之不能共存。
老 Z 不在乎自己 AC 多少题。请告诉他,他最多能从“善良 OJ”上获取木马的个数。
【输入】
第一行,一个正整数 n,表示木马个数。
剩余(n-1)行,每行一对木马,表示他们不能共存。(保证相同的木马可以共存,任意不同两
行的描述不等价)
木马编号从 0 至(n-1)
【输入】
一行,老 Z 最多获得木马的个数。你可以认为开始时没有任何木马。
【输入样例】
3
0 1
1 2
【输出样例】
2
【数据规模】
对于 100%的数据,1<=n<=200 很明显的裸题。(*^▽^*)。
附上代码
#include<cstdio> #include<algorithm> #define N 200+10 using namespace std; int f[N<<1][2],head[N<<1],num=1; struct Edge{ int next,to; }e[N<<1]; void add(int from,int to) { e[++num]=(Edge){head[from],to}; head[from]=num; } void insert(int from,int to) { add(from,to); add(to,from); } int dp(int u,int fa) { f[u][0]=1; f[u][1]=0; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v==fa)continue; dp(v,u); f[u][0]+=f[v][1]; f[u][1]+=max(f[v][0],f[v][1]); } return max(f[u][0],f[u][1]); } int main() { freopen("blackoj.in","r",stdin); freopen("blackoj.out","w",stdout); int n; scanf("%d",&n); for(int i=1;i<=n-1;i++) { int u,v; scanf("%d%d",&u,&v); insert(u,v); } printf("%d ",dp(0,0)); fclose(stdout); return 0; }