讨论
树形dp,利用深搜处理每个人,对于每个人而言,都有自己来或不来所得到的活跃度,都要记录下来,每个人的活跃度初始化到自己来的状态上,对于每个人,如果自己不来,从每个直接下属来或不来中取较大者加到自己身上,如果自己来,把每个直接下属不来加到自己身上,最后取boss来或不来的最大值返回即可
实现上,没什么可说的,只是读题的时候需要仔细一点,前者是下属,后者是上司
题解状态
124MS,1544K,979 B,G++
题解代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 6004
#define memset0(a) memset(a,0,sizeof(a));
int N;//总人数
int dp[2][MAXN];//0是自己不来 1是自己来
int to[MAXN], pre[MAXN], al[MAXN], index;//当作图来处理的 四个静态邻接表的东西
bool not_root[MAXN];//不是boss 显然有上司的不是
void dfs(int a)
{
for (int p = al[a]; p; p = pre[p]) {
int b = to[p];
dfs(b);
dp[0][a] += max(dp[1][b], dp[0][b]);//自己不来 直接下属二者取较大
dp[1][a] += dp[0][b];//自己来 下属肯定不来
}
}
int fun()
{
index = 1;
for (int p = 1; p <= N; p++)
scanf("%d", &dp[1][p]);//input//直接初始化为自己来的状态
int b, a;
while (scanf("%d%d", &b, &a) && (a || b)) {//input
to[index] = b, pre[index] = al[a], al[a] = index++;
not_root[b] = 1;
}
int boss = find(not_root + 1, not_root + N + 1, false) - not_root;//找出boss
dfs(boss);
return max(dp[0][boss], dp[1][boss]);
}
int main()
{
//freopen("vs_cin.txt", "r", stdin);
//freopen("vs_cout.txt", "w", stdout);
while (~scanf("%d", &N)) {//input
printf("%d\n", fun());//output
memset0(al);
memset0(dp[0]);
memset0(not_root)
}
}
EOF