目录
1. 题目描述
2. 思路描述 :树形dp
采用树形动态规划(DP)的方法,从叶子节点向上搜索。首先,寻找树的根节点,然后通过DFS(深度优先搜索)遍历树的结构。在DFS过程中,更新每个节点的两种状态(选择或不选择),以计算最大幸福值。最终,输出根节点的最大幸福值作为答案。
1. 我们有两种搜索方法,第一种是从根节点向下搜到子节点,第二种是从子节点向上搜到根节点
如果从上往下搜,我们无法确定他被选或者不被选的f[][],无法写出表达式,而从下往上搜可以,
所以我们从下向上搜
2.
3. 代码解释:
1)确定根节点root:
这道题中,并没有提及这棵树的根节点是什么,所以我们要找到根节点,便于最后输出
在之前我们假设每个点 i 的父节点是他自己,后面建图时改为正确的根节点
然后搜索,如果他的父节点还是自己,那他就是根节点root
建边纯纯模板,先不放部分代码
int main()
{
int l,k;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>r[i];
fa[i]=i;
}
for(int i=1;i<=n-1;i++)
{
cin>>l>>k;
add(k,l);
fa[l]=k;
}
for(int i=1;i<=n;i++)
{
if(fa[i]==i)
{
root=i;
break;
}
}
dfs(root);
int ans=0;
ans=max(f[root][1],f[root][0]);
cout<<ans;
}
2)dfs
根据思路图,直接写
void dfs(int t)
{
f[t][1]=r[t];
for(int i=head[t];i;i=ne[i])
{
int g=e[i];
dfs(g);
f[t][1]+=f[g][0];
f[t][0]+=max(f[g][1],f[g][0]);
}
}
要注意的是,如果要选择点t,先把f[t][1]加上t点的happy值
4. 完整代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int r[6005];
int e[6005],head[6005],idx=1,ne[6005];
int f[6005][2];
int root;
int fa[6005];
int sum[6005];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=head[a];
head[a]=idx++;
}
void dfs(int t)
{
f[t][1]=r[t];
for(int i=head[t];i;i=ne[i])
{
int g=e[i];
dfs(g);
f[t][1]+=f[g][0];
f[t][0]+=max(f[g][1],f[g][0]);
}
}
int main()
{
int l,k;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>r[i];
fa[i]=i;
}
for(int i=1;i<=n-1;i++)
{
cin>>l>>k;
add(k,l);
fa[l]=k;
}
for(int i=1;i<=n;i++)
{
if(fa[i]==i)
{
root=i;
break;
}
}
dfs(root);
int ans=0;
ans=max(f[root][1],f[root][0]);
cout<<ans;
return 0;
}