ALGO-4 结点选择
结点选择
50%
这道题是树形动态规划,参考了大佬的代码
由于JAVA的一些原因,C++能满分的代码用JAVA只能过一半的数据
首先需要读懂题目
第一行是结点的个数
第二行是每个结点的权
再向下是树的边(不分父子)
建立两个全局二维数组
tree[i][j]=a(a!=0)代表树有一条i到a的边,每行个数取决于i结点和其他结点有几条边
dp[i][0]代表i结点i不选中时的所有权值之和
dp[i][1]代表结点i选中时所有权值之和
首先将结点i的权值存在dp[i][1]中作为初始值
将边存储在tree[][]中,注意由于不区分父子结点,需要双向添加(maketree函数)
重点是dfs方法,深度优先搜索
从结点1开始进行深度优先搜索,需要注意当该结点的父节点子节点相同时,不进行任何操作,以防计算重复
核心的语句
//选择x结点时,添加x相邻的结点x_son未选中时的权值
dp[x][1] += dp[x_son][0];
//不选择x结点时,添加x相邻结点选中或者不选中时最大的值
dp[x][0] += Math.max(dp[x_son][0], dp[x_son][1]);
最终的结果就是输出结点1选中或者未选中中较大的值
为了搞懂这个过程最好画个图模拟过程以便更好地理解
code
import java.util.Scanner;
public class Main {
static int tree[][];
static int dp[][];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
tree = new int[n + 1][n + 1];
dp = new int[n + 1][2];
int i, j;
for (i = 0; i < n; i++) {
dp[i + 1][1] = scanner.nextInt();
}
for (i = 1; i < n; i++) {
int x = scanner.nextInt();
int y = scanner.nextInt();
maketree(x, y);
}
dfs(1, 0);
System.out.println(Math.max(dp[1][0], dp[1][1]));
}
public static void maketree(int x, int y) {
int i = 0, j = 0;
while (tree[x][i] != 0)
i++;
tree[x][i] = y;
while (tree[y][j] != 0)
j++;
tree[y][j] = x;
}
public static void dfs(int x, int x_father) {
int x_son = tree[x][0];
int i, j, k;
for (i = 0; x_son != 0; i++) {
x_son = tree[x][i];
if (x_son != x_father) {
dfs(x_son, x);
dp[x][1] += dp[x_son][0];
dp[x][0] += Math.max(dp[x_son][0], dp[x_son][1]);
}
}
}
}