7.树形DP
AcWing 285. 没有上司的舞会
实现思路:所求即为从一棵中选出一个结点集合其各结点的值之和最大,且这个结点集合中都没有这些结点的父节点存在(没有父亲,只有同辈或者隔辈)
状态表示:利用递归
f(u, 0)
:从所有以u为根结点的子树中选择,并且不选u这个点的满足条件的最大快乐数
不选择u这个点,那么看u的子节点Si,子节点Si可以去,也可以不去,那么再以这个子节点Si为根节点研究,看其去与不去情况下的快乐数选大者,即max(f[si][1],f[si][0])
,再将所有子节点的快乐数求和即为此状况下的最大快乐数
f(u, 1)
:从所有以u为根结点的子树中选择,并且选择u这个点的满足条件的最大快乐数
此时,u的子节点Si都不可以去,那么只能看其所有子节点不去情况下f[Si][0]
的快乐数,再求和为最终快乐数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=6010; int f[N][2],happy[N]; int e[N],h[N],ne[N],idx; bool has_father[N]; int n;
void add(int a,int b){ e[idx]=b; ne[idx]=h[a]; h[a]=idx++; }
void dfs(int u){ f[u][1]=happy[u]; for(int i=h[u];i!=-1;i=ne[i]){ int j=e[i]; dfs(j); f[u][0]+=max(f[j][0],f[j][1]); f[u][1]+=f[j][0]; } }
int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>happy[i]; memset(h,-1,sizeof h); n-=1; while(n--){ int a,b; cin>>a>>b; has_father[a]=b; add(a,b); } int root=1; while(has_father[root]) root++; dfs(root); cout<<max(f[root][0],f[root][1]); return 0; }
|