题意:
有一个树,每个点有个权值,每条边是单向的,询问父亲节点和儿子节点不能同时存在的最大权值和
思路:
简单树形dp,定义dp[x][0]表示为搜索到x节点且x节点不存在情况的最大值,dp[x][1]为x节点存在情况的最大值。
d
p
[
x
]
[
0
]
=
∑
v
为
x
儿
子
节
点
max
(
d
p
[
v
]
[
1
]
,
d
p
[
v
]
[
0
]
)
dp[x][0]=\sum_{v为x儿子节点}\max(dp[v][1],dp[v][0])
dp[x][0]=∑v为x儿子节点max(dp[v][1],dp[v][0])
d
p
[
x
]
[
1
]
=
v
a
l
[
x
]
+
∑
v
为
x
儿
子
节
点
d
p
[
v
]
[
0
]
dp[x][1]=val[x] + \sum_{v为x儿子节点}dp[v][0]
dp[x][1]=val[x]+∑v为x儿子节点dp[v][0]
可以根据入度判断是不是没有更高级别的节点
#include<bits/stdc++.h>
using namespace std;
const int N=6e3+5;
const int INF=1e9+7;
int val[N];
vector<int>mp[N];
int dp[N][2];
int du[N];
void dfs(int u){
int ed=mp[u].size();
dp[u][1]=val[u];
dp[u][0]=0;
for(int i=0;i<ed;i++){
int v=mp[u][i];
dfs(v);
dp[u][1]+=dp[v][0];
dp[u][0]+=max(dp[v][0],dp[v][1]);
}
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&val[i]);
}
for(int i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
mp[y].push_back(x);
du[x]++;
}
memset(dp,250,sizeof(dp));
int ans=-INF;
for(int i=1;i<=n;i++){
if(!du[i]){
dfs(i);
ans=max(ans,max(dp[i][1],dp[i][0]));
}
}
printf("%d\n",ans);
return 0;
}