题目链接:没有上司的舞会 - 洛谷
思路:用 f 数组 和 g 数组 维护
f [ i ] 代表不选 i结点 最大的快乐指数
g [ i ] 代表选 i 结点 最大快乐指数
转移方程:
for j = i 的子节点(下属)
f[i]+=max(g[j],f[j])
g[i]+=max(0,f[j])
代码:
#include<iostream>
using namespace std;
const int N = 100005;
const int M = 200005;
int ne[M],to[M],w[M],head[N];
int cnt;
int r;
int n,u,v;
int f[N],g[N];
bool boss[N];
void add(int u,int v)
{
cnt++;
ne[cnt]=head[u];
to[cnt]=v;
head[u]=cnt;
}
void dfs(int x)
{
f[x]=0;
g[x]=max(0,w[x]);
for(int i=head[x];i;i=ne[i])
{
int y=to[i];
dfs(y);
f[x]+=max(f[y],g[y]);
g[x]+=max(0,f[y]);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;++i) cin>>w[i];
for(int i=1;i<n;++i)
{
cin>>u>>v;
add(v,u);
boss[u]=true;
}
for(int i=1;i<=n;++i) if(!boss[i]) r=i;
dfs(r);
for(int i=1;i<=n;++i)
{
//cout<<f[i]<<" "<<g[i]<<endl;
//cout<<boss[i]<<endl;
}
cout<<max(f[r],g[r]);
return 0;
}