Luogu P1352 没有上司的舞会 题解报告

题目传送门

【题目大意】

有n个职员,编号为1~n,他们之间的关系就像一棵数,父节点是子结点的直接上司,每个职员有一个快乐指数$H_i$,,且所有职员都不愿意跟自己的直接上司一起参加舞会,求所有参加舞会的职员的快乐指数最大值。

【思路分析】

设f[i][0]表示编号为i的结点不参加舞会时,以i结点为根的子树的快乐指数最大值;f[i][1]表示i结点参加舞会时,以i结点为根的子树的快乐指数最大值,易得转移方程:$$f[i][0]=\sum_{x\in son[i]}max(f[x][0],f[x][1])$$

$$f[i][1]=H[i]+\sum_{x\in son[i]}f[x][0]$$其中son[i]表示i结点的子结点集合。

【代码实现】

 1 #include<bits/stdc++.h>
 2 #define rg register
 3 #define go(i,a,b) for(rg int i=a;i<=b;i++)
 4 #define back(i,a,b) for(rg int i=a;i>=b;i--)
 5 #define ll long long
 6 #define mem(a,b) memset(a,b,sizeof(a))
 7 using namespace std;
 8 const int N=10002;
 9 vector<int> son[N];
10 int f[N][2],h[N],n,fa[N];
11 void dp(int x){
12     f[x][0]=0;f[x][1]=h[x];
13     int size=son[x].size();
14     go(i,0,size-1){
15         int y=son[x][i];
16         dp(y);
17         f[x][0]+=max(f[y][1],f[y][0]);
18         f[x][1]+=f[y][0];
19     }
20     return;
21 }
22 int main(){
23     scanf("%d",&n);
24     go(i,1,n) scanf("%d",&h[i]);
25     go(i,1,n-1){
26         int x,y;
27         scanf("%d%d",&x,&y);
28         fa[x]=y;
29         son[y].push_back(x);
30     }
31     int root;
32     go(i,1,n) if(!fa[i]){root=i;break;}
33     dp(root);
34     printf("%d\n",max(f[root][1],f[root][0]));
35     return 0;
36 }
代码戳这里

 

posted @ 2019-06-11 09:55  小叽居biubiu  阅读(139)  评论(0编辑  收藏  举报