树形动态规划(最大子独立集)

本文详细探讨了如何解决最大子独立集问题,通过输入、输出样例进行说明,并提供了完整的分析和代码实现。文章指出,由于题目没有明确父节点,采用动态数组存储父子关系,并在函数中维护父亲节点来判断。此外,还讨论了如何处理涉及字符串输入的情况,提出了使用关联式容器如map将字符串与编号关联的思路。
摘要由CSDN通过智能技术生成

最大子独立集

对于一棵有N个结点的无根树,选出尽量多的结点,使得任何两个结点均不相邻(称为最大独立集)。

输入

 第1行:1个整数N(1 <= N <= 6000),表示树的结点个数,树中结点的编号从1..N
接下来N-1行,每行2个整数u,v,表示树中的一条边连接结点u和v

输出

 第1行:1个整数,表示最大独立集的结点个数

样例输入

11
1 2
1 3
3 4
3 5
3 6
4 7
4 8
5 9
5 10
6 11

样例输出

7

分析

这一题是学习树形DP的基础,要求掌握,题目本身不难,只是树形DP入门。
由题意可知,当我们选择一个点时,就不能选择与它相邻的。所以这个点分为选与不选两种状态。
所以定义状态Dp[i][1](选择i点的最优解),Dp[i][0](不选i点的最优解)。
最后的解就是Dp[root][1]与Dp[root][0]中大的那个,root是根节点。
可能会问:题目不是说无根树吗?
对,这里是无根树,但由于算法需求,我们先转成有根数,即随便找一个点当根(此后,就一直以它为根)。
在学习树形Dp的阶段,会遇到很多需要无根转有根的。
废话就不多说了,接下来看状态转移方程。
想一想,Dp[i][1]能从什么状态转过来,
这很好想,既然i这个点选了,那它儿子就不选呀。
所以Dp[i][1]+=Dp[v][0]; 其中,v是儿子编号,至于‘+=’嘛,因为答案是叫求和。
那Dp[i][0]呢?
i选了,它儿子必须选吗?
所以Dp[i][0]+=max(Dp[v][0],Dp[v][1]);

下面给出完整代码(注释)
差点忘了,还有输入
题目只是说两边相连,但并没有说谁是父亲。
所以我们用一个动态数组存点的儿子
所以输入点x,y时
就把x的儿子存成y
y的儿子存成x
在求解时,函数传参时维护一个父亲,
只需判断儿子是不是父亲即可。
下面是完整代码

Code

#include<cstdio>
#include<vector>
#include<iostream>
using namespace std;
int n;
int Dp[6005][2];//状态
vector<int>G[6005];//儿子 
void Tdp(int x,int fa){
    Dp[x][1]=
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值