codevs 1380:没有上司的舞会

题目描述 Description
      Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。

输入描述 Input Description
第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0,0。

输出描述 Output Description
输出最大的快乐指数。

样例输入 Sample Input
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

样例输出 Sample Output
5

数据范围及提示 Data Size & Hint
各个测试点1s
题目

  芒果君:这道树形DP首先在建图上有一点难度,其实很像邻接表。不过在我写完上句话构思的时候突然看到一个更简单的方法,就是用vector储存子节点再进行递归。找到没有父亲的节点当作祖宗进行DFS(DP),DP决策的部分主要抓住状态——这个人参不参加舞会(是非用1、0表示),f[x]数组表示以x为根节点的最优解。如果参加,就继承他子节点不参加的情况,f[x][1]+=f[son][0];不参加则相反,但要注意,由于每个点的权值有正有负,他的子节点可参加可不参加,即f[x][0]+=max(f[son][0],f[son][1])。

  

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #define l 6010
 5 using namespace std;
 6 struct Node{
 7     int fa,so,ne;
 8 }p[l];
 9 int n,cnt,exfa[l],w[l],f[l][2],hl[l];
10 void add(int x,int y)
11 {
12     p[++cnt].fa=x;
13     p[cnt].so=y;
14     p[cnt].ne=hl[x];
15     hl[x]=cnt;
16 }
17 int find()
18 {
19     for(int i=1;i<=n;++i) if(!exfa[i]) return i;
20 }
21 void dfs(int x)
22 {
23     f[x][1]=w[x];
24     f[x][0]=0;
25     if(!hl[x])    return;
26     for(int i=hl[x];i;i=p[i].ne){
27         dfs(p[i].so);
28         f[x][1]+=f[p[i].so][0];
29         f[x][0]+=max(f[p[i].so][1],f[p[i].so][0]);
30     }
31 }
32 int main()
33 {
34     int x,y;
35     scanf("%d",&n);
36     for(int i=1;i<=n;++i) scanf("%d",&w[i]);
37     while(1){
38         scanf("%d%d",&x,&y);
39         if(!x&&!y) break;
40         add(y,x);
41         exfa[x]=1;
42     }
43     int an=find();
44     dfs(an);
45     printf("%d
",max(f[an][0],f[an][1]));
46     return 0;
47 }
原文地址:https://www.cnblogs.com/12mango/p/7205949.html