第10题 生命之树(树形dp)
给定一颗无根树,求出一个字数,所有节点的权值之和最大。求出最大的数是多少。
题目思路:
对于每个结点的决策有2种,分别是选择和不选择,那么我们定义dp[ i ][ 0 ] 和 dp[ i ][ 1 ]分别表示不选择(选择) i 结点能得到的最大权值和。
状态转移方程是:dp [ i ] [ 1 ] = sum(max(dp[ j ][ 1 ] , dp[ j ][ 0 ])); j 是 i 的孩子结点 。
dp[ i ][ 0 ] = 0;
#include<cstdio>
#include<cstring>
#include<vector>
#define N 100005
using namespace std;
vector<int> node[N];
int dp[N][2];
int v[N],vis[N];
int n,a,b;
void dfs(int u){
dp[u][1] = v[u];
dp[u][0] = 0;
vis[u]=1;
for(int i=0 ;i<node[u].size();i++){
if(!vis[node[u][i]]){
dfs(node[u][i]);
dp[u][1] += max(dp[node[u][i]][1],dp[node[u][i]][0]);
}else{
dp[u][1] = max(dp[u][1],v[u]);
dp[u][0] = max(dp[u][0],0);
}
}
}
void init(){
memset(v,0,sizeof(v));
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(int i=1 ;i<=n ;i++){
scanf("%d",&v[i]);
}
for(int i=1 ;i<n ;i++){
scanf("%d%d",&a,&b);
node[a].push_back(b);
node[b].push_back(a);
}
}
int main(){
init();
dfs(1);
int ans = -1;
for(int i=1 ;i<=n ;i++){
ans = max(ans,dp[i][1]);
ans = max(ans,dp[i][0]);
}
printf("%d\n",ans);
return 0;
}