此题类似于打家劫舍的树形问题:打家劫舍 III
Ural大学有N名职员,编号为1~N。
他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。
每个职员有一个快乐指数,用整数 HiHi 给出,其中 1≤i≤N1≤i≤N。
现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。
在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。
输入格式
第一行一个整数N。
接下来N行,第 i 行表示 i 号职员的快乐指数HiHi。
接下来N-1行,每行输入一对整数L, K,表示K是L的直接上司。
输出格式
输出最大的快乐指数。
数据范围
1≤N≤60001≤N≤6000,
−128≤Hi≤127−128≤Hi≤127
输入样例:
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
输出样例:
5
//假设幸福值一样并且每个上司最多俩员工的话,这道题就变成树状问题的打家劫舍
//本质上还是打家劫舍问题
import java.io.*;
import java.lang.*;
import java.util.*;
class Main{
static int n = 0, N = 6010;
static int[] Happy = new int[N];//幸福值
static int[] h = new int[N];//邻接表
static int[] e = new int[N], ne = new int[N];//图的单链表
static int idx = 1;
static int[][] f = new int[N][2];//状态数组
static boolean[] st = new boolean[N];
static void add(int a, int b){//建表
e[idx] = b; ne[idx] = h[a]; h[a] = idx++;
}
static void dfs(int u){
f[u][1] = Happy[u];
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
dfs(j);
f[u][0] += Math.max(f[j][0], f[j][1]);
f[u][1] += f[j][0];
}
}
public static void main(String[] args)throws Exception{
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
n = Integer.valueOf(buf.readLine());
for(int i = 1; i <= n; ++i){//存储幸福值
Happy[i] = Integer.valueOf(buf.readLine());
}
Arrays.fill(h, -1);
int m = n - 1;
while( m -- != 0 ) {
String[] info = buf.readLine().split(" ");
int a = Integer.valueOf(info[0]);
int b = Integer.valueOf(info[1]);
add(b, a);//因为b是上司因此需要把a连接到b的后面
st[a] = true;//表示当前节点有父节点
}
//计算得到根节点
int u = 1;
while(st[u]){
u++;
}
dfs(u);
System.out.print(Math.max(f[u][0], f[u][1]));
}
}
类比打家劫舍III的代码
class Solution {
public int rob(TreeNode root) {
if( root == null )return 0;
int[] res = max( root );
return Math.max( res[0], res[1]);
}
public int[] max(TreeNode root){
int[] res = new int[2];
if( root == null )return res;
int[] left = max( root.left );
int[] right = max( root.right );
res[0] = Math.max(left[0], left[1]) + Math.max(right[0],right[1]);//不选根节点
res[1] = root.val + left[0] + right[0];//选根节点
return res;
}
}