【Luogu】P1352没有上司的舞会(树形DP)
设f[i][0]表示第i个人不去舞会时子树的最大欢乐度,f[i][1]表示第i个人去舞会时子树的最大欢乐度。
则有状态转移方程:f[i][0]+=∑max(f[to][0],f[to][1])
f[i][1]+=∑f[to][0]
其中to是i的所有直连子节点。
初始化:f[i][1]=第i个人自己的欢乐度。
我发现好像我做过的树形DP都是基于DFS搞的。这可能是个规律。
#include <cstdio> #include <cstring> #include<algorithm> using namespace std; int que[10000]; bool indl[10000]; struct Edge{ int next,to; }edge[100000]; int head[10000],num; inline void add(int from,int to){ edge[++num]=(Edge){head[from],to}; head[from]=num; } int f[10000][2]; void dfs(int x){ for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; dfs(to); f[x][0]+=max(f[to][0],f[to][1]); f[x][1]+=f[to][0]; } f[x][1]+=que[x]; return; } int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&que[i]); for(int i=1;i<n;++i){ int from,to; scanf("%d%d",&from,&to); add(to,from); indl[from]=1; } int start; for(int i=1;i<=n;++i){ if(!indl[i]){ start=i; break; } } dfs(start); printf("%d",max(f[start][0],f[start][1])); return 0; }