题目
同洛谷经典树形DP例题 没有上司的舞会,简单来说,就是建树形图,父子节点最多取其一,取父节点就不能取子节点,取子节点就不能取父节点
树形DP的模板题
题解
直接给出动态规划方程:
f[father][0]+=max(f[son][0],f[son][1])
f[father][1]+=f[son][0]
很好理解,0代表不取,1,代表取,同经典背包问题,取了父节点自然只能不取子节点,不取父节点就对子节点没有影响,选取最大的那个
代码
#include<bits/stdc++.h>
using namespace std;
const int M=10000;
int happy[M],head[M],shu[M][2];
struct N
{
int to,nex;
}edge[M];
int cnt=0;
void add_edge(int x1,int x2)
{
edge[++cnt].to=x2;
edge[cnt].nex=head[x1];
head[x1]=cnt;
}
bool is_son[M];
void treaDP(int S)
{
shu[S][0]=0;
shu[S][1]=happy[S];
int m;
for(int i=head[S];i!=-1;i=edge[i].nex)
{
m=edge[i].to;
treaDP(m);
shu[S][0]+=max(shu[m][0],shu[m][1]);
shu[S][1]+=shu[m][0];
}
}
int main()
{
int n,m,k,x1,x2,x3,ans1,ans2,S;
while(scanf("%d",&n)==1)
{
cnt=0;
memset(head,-1,sizeof(head));
//memset(shu,0,sizeof(shu));
for(int i=1;i<=n;i++)
{
scanf("%d",&happy[i]);
}
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&x1,&x2);
is_son[x1]=1;
add_edge(x2,x1);
}
scanf("%d%d",&x1,&x2);
for(int i=1;i<=n;i++)
{
if(!is_son[i])
{
S=i;
break;
}
}
treaDP(S);
cout<<max(shu[S][0],shu[S][1])<<endl;
}
}