中考前逃来机房学树形DP和状压DP。
典型的树形DP嘛。
dp数组开2维,第一维表示在第i个点,第二位表示去或不去,去为1,不去为0。
状态转移方程很简单:
当前节点不去的话,就加上儿子节点中去或不去的最大值. dp[i][0]+=max(dp[j][0],dp[j][1]);
当前节点去的话,就直接加上儿子节点不去的值和当前快乐值. dp[i][1]=dp[j][0]+happy[i];
然后找到校长的编号,往下递归就好了.
噫,代码如下:
#include<bits/stdc++.h>
using namespace std;
vector<int>fas[10010];//用vector来存树
int n,root;
int happy[10010],dp[10010][2];
bool head[10010];
void dg(int);
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",happy+i);
}
for(int i=1;i<=n-1;i++)
{
int father,son;
scanf("%d%d",&son,&father);
fas[father].push_back(son);//把一个节点的所有儿子存在vector里
head[son]=true;
}
int a,b;
scanf("%d%d",&a,&b);
for(int i=1;i<=n;i++)
{
if(head[i]==false)//根节点没有父亲节点
{
root=i;
break;
}
}
dg(root);
printf("%d",max(dp[root][1],dp[root][0]));
return 0;
}
void dg(int x)
{
dp[x][0]=0;
dp[x][1]=happy[x];//先赋初值,不去的话最大值为0,去的话为自己的快乐值
for(int i=0;i<fas[x].size();i++)//遍历一个点的所有儿子
{
int y=fas[x][i];
dg(y);
dp[x][0]+=max(dp[y][0],dp[y][1]);
dp[x][1]+=dp[y][0];
}
}