0
点赞
收藏
分享

微信扫一扫

Anniversary party POJ - 2342


第一道树形dp题目 虽然a了 但理解还是不到位

 

补坑 dp[i][0]代表节点i不去舞会时整棵子树最大欢愉度 dp[i][1]相反 当前节点从所有子节点转移过来即可 因为兄弟节点之间是互不相干的

转移方程 dp[i][0]+=max(dp[j][0],dp[j][1]) dp[i][1]+=dp[j][0] 其中dp[i][0]+=max(dp[j][0],dp[j][1]) 代表i节点不参加 其子节点未必一定要去 dp[i][1]+=dp[j][0]代表i去了舞会其子节点肯定去不了

注意不要想当然写成dp[i][0]+=dp[j][1] 这就相当于统计奇偶层的权值和了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=6e3+10;

struct node
{
int v,next;
};

node edge[maxn];
int dp[maxn][2];
int val[maxn],first[maxn],book[maxn];
int n,num,root;

void addedge(int u,int v)
{
edge[num].v=v;
edge[num].next=first[u];
first[u]=num++;
}

void dfs(int cur)
{
int i,v;
dp[cur][0]=0,dp[cur][1]=val[cur];
for(i=first[cur];i!=-1;i=edge[i].next){
v=edge[i].v;
dfs(v);
dp[cur][0]+=max(dp[v][0],dp[v][1]),dp[cur][1]+=dp[v][0];
}
}

int main()
{
int i,u,v;
while(scanf("%d",&n)!=EOF){
if(n==0){
scanf("%d",&n);
break;
}
for(i=1;i<=n;i++){
scanf("%d",&val[i]);
}
memset(first,-1,sizeof(first));
memset(book,0,sizeof(book));
num=0;
for(i=1;i<=n-1;i++){
scanf("%d%d",&v,&u);
addedge(u,v);
book[v]=1;
}
for(i=1;i<=n;i++){
if(!book[i]){
root=i;
break;
}
}
dfs(root);
printf("%d\n",max(dp[root][0],dp[root][1]));
}
return 0;
}

 

 

 


举报

相关推荐

0 条评论