题目描述
某大学有 nnn 个职员,编号为 1…n1\ldots n1…n。
他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。
现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 rir_iri,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。
所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。
输入格式
输入的第一行是一个整数 nnn。
第 222 到第 (n+1)(n + 1)(n+1) 行,每行一个整数,第 (i+1)(i+1)(i+1) 行的整数表示 iii 号职员的快乐指数 rir_iri。
第 (n+2)(n + 2)(n+2) 到第 2n2n2n 行,每行输入一对整数 l,kl, kl,k,代表 kkk 是 lll 的直接上司。
输出格式
输出一行一个整数代表最大的快乐指数。
输入输出样例
输入 #1
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
输出 #1
5
说明/提示
数据规模与约定
对于 100%100%100% 的数据,保证 1≤n≤6×1031\leq n \leq 6 \times 10^31≤n≤6×103,−128≤ri≤127-128 \leq r_i\leq 127−128≤ri≤127,1≤l,k≤n1 \leq l, k \leq n1≤l,k≤n,且给出的关系一定是一棵树。
基础树形dp 类似于打家劫舍那道题
定义状态 :
- dp[i][0]表示
选择
节点i
的最优值 - dp[i][1]表示
不选
节点i
的最优值
转移方程 :
- d p [ i ] [ 0 ] = m a x ( d p [ i ] [ 0 ] , d p [ i ] [ 0 ] + d p [ j ] [ 1 ] ) 选 了 i 就 不 能 选 i 的 子 节 点 dp[i][0]=max(dp[i][0],dp[i][0]+dp[j][1])\\选了i就不能选i的子节点 dp[i][0]=max(dp[i][0],dp[i][0]+dp[j][1])选了i就不能选i的子节点
-
d
p
[
i
]
[
1
]
=
dp[i][1]=
dp[i][1]=
m
a
x
(
d
p
[
i
]
[
1
]
,
d
p
[
j
]
[
1
]
,
d
p
[
j
]
[
0
]
,
d
p
[
i
]
[
1
]
+
d
p
[
j
]
[
1
]
,
d
p
[
i
]
[
1
]
+
d
p
[
j
]
[
0
]
)
max(dp[i][1],dp[j][1],dp[j][0],\\ ~~~~~~~~~~~~~~~~~~~~~~~~~~dp[i][1]+dp[j][1],dp[i][1]+dp[j][0])
max(dp[i][1],dp[j][1],dp[j][0], dp[i][1]+dp[j][1],dp[i][1]+dp[j][0])
如果不选i
,则可以选或不选
i 的子节点,也可只要其中一个或多个
子节点
边界条件 :
-
d
p
[
i
]
[
0
]
=
w
[
i
]
dp[i][0]=w[i]
dp[i][0]=w[i]当选择一个节点
V
,至少有w[V]
的权值
#define debug
#ifdef debug
#include <time.h>
#endif
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>
#define MAXN ((int)1e5+7)
#define ll long long int
#define INF (0x7f7f7f7f)
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)
using namespace std;
#define show(x...) \
do { \
cout << "\033[31;1m " << #x << " -> "; \
err(x); \
} while (0)
void err() { cout << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }
namespace FastIO{
char print_f[105];
void read() {}
void print() { putchar('\n'); }
template <typename T, typename... T2>
inline void read(T &x, T2 &... oth) {
x = 0;
char ch = getchar();
ll f = 1;
while (!isdigit(ch)) {
if (ch == '-') f *= -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - 48;
ch = getchar();
}
x *= f;
read(oth...);
}
template <typename T, typename... T2>
inline void print(T x, T2... oth) {
ll p3=-1;
if(x<0) putchar('-'), x=-x;
do{
print_f[++p3] = x%10 + 48;
} while(x/=10);
while(p3>=0) putchar(print_f[p3--]);
putchar(' ');
print(oth...);
}
} // namespace FastIO
using FastIO::print;
using FastIO::read;
int n, m, Q, K, w[MAXN], vis[MAXN], dp[MAXN][2];
vector<int> G[MAXN];
// dp[i][0] 选 i
// dp[i][1] 不选 i
void dfs(int u) {
if(G[u].empty()) {
dp[u][0] = w[u];
return ;
}
dp[u][0] = w[u];
for(auto v : G[u]) {
dfs(v);
dp[u][0] = max({ dp[u][0], dp[u][0]+dp[v][1] });
dp[u][1] = max({ dp[u][1], dp[v][0], dp[v][1],
dp[u][1]+dp[v][0], dp[u][1]+dp[v][1] });
}
}
signed main() {
#ifdef debug
freopen("test.txt", "r", stdin);
clock_t stime = clock();
#endif
read(n);
for(int i=1; i<=n; i++) read(w[i]);
for(int i=1; i<n; i++) {
int chl, fat;
read(chl, fat);
vis[chl] = true;
G[fat].push_back(chl);
}
int root = 0;
for (int i=1; i<=n && !root; i++)
root = (vis[i] ? 0 : i);
dfs(root);
printf("%d\n", max(dp[root][0], dp[root][1]));
#ifdef debug
clock_t etime = clock();
printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif
return 0;
}