【POJ】2342 Anniversary party 树形dp

来源:互联网 发布:csol频繁网络问题 编辑:程序博客网 时间:2024/06/05 10:19

题目传送门

曾经身为蒟蒻的我对树形dp一无所知,现在依然身为蒟蒻的我认为树形dp不是不能做。

要相信蒟蒻也是有明天的。

Flag:树形dp入门题,从此我入了树形dp的坑。

设f[i][0~1]为第i个人是否出席的最大快乐指数。(0表示没出席,1则反之)

状态转移方程也非常好写:设j为i的下属,

1.若第i个人出席,则f[i][1]+=f[j][0]

2.若第i个人不出席,则f[i][0]+=max(f[j][0],f[j][1])

最后,因为题中所给出的图为一棵树,则答案就是max(f[rt][0],f[rt][1]),其中rt为树根。

附上AC代码:

#include <cstdio>#include <cctype>#include <algorithm>#define N 6010using namespace std;struct side{int to,nt;}s[N<<1];int n,a[N],x,y,num,h[N],rt,fa[N],f[N][2];inline char nc(){static char ch[100010],*p1=ch,*p2=ch;return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;}inline void read(int &a){static char c=nc();int f=1;for (;!isdigit(c);c=nc()) if (c=='-') f=-1;for (a=0;isdigit(c);a=a*10+c-'0',c=nc());a*=f;return;}inline void add(int x,int y){s[++num]=(side){x,h[y]},h[y]=num,fa[x]=y;}inline void so(int x,int fa){f[x][1]=a[x];for (int i=h[x]; i; i=s[i].nt)if (s[i].to!=fa)so(s[i].to,x),f[x][1]+=f[s[i].to][0],f[x][0]+=max(f[s[i].to][0],f[s[i].to][1]);return;}int main(void){read(n);for (int i=1; i<=n; ++i) read(a[i]);for (int i=1; i<n; ++i) read(x),read(y),add(x,y);rt=1;while (fa[rt]) rt=fa[rt];so(rt,0);printf("%d",max(f[rt][0],f[rt][1]));return 0;}