AcWing 285. 没有上司的舞会(树形DP)

此题类似于打家劫舍的树形问题:打家劫舍 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;
    }
}

 

你可能感兴趣的:(AcWing)