https://blog.csdn.net/qq_32823673/article/details/56838405
刚开始代码,这个代码有点问题,不知道为什么一直报空指针异常
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Test{
static int MAx = 1000001;
static int p[] = new int[MAx];
static List<Integer>[]g ;
static int n;
static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
g= new ArrayList[MAx];
initG();//list数组里每一个都要初始化一下称为一个小的list,不然不能用
n = sc.nextInt();
intputtree(n);
int root = sc.nextInt();
p[root] = -1;
dfs(root, p[root]);
for(int i = 0;i<n;i++){
System.out.print(p[i]+" ");
}
}
static void dfs(int u ,int fa){
for(int i = 0;i<g[u].size();i++){
Integer child = g[u].get(i);
if(child==fa) continue;//这是啥,就这一行,没有他就全报stackoverflow!!!因为会死循环的!!
dfs(child,u);
}
p[u] = fa; //这里应该是对的,,
}
static void initG(){
for(int i=0;i<n;i++){
g[i] = new ArrayList<Integer>();
}
}
static void intputtree(int n){
int u,v;
for(int i = 0;i<n-1;i++){
u = sc.nextInt();
v = sc.nextInt();
g[u].add(v);
g[v].add(u);
}
}
}
不太理解
输入:
8
0 1
0 2
0 3
1 4
1 5
5 6
5 7
1
输出:
1 -1 0 0 1 1 5 5
例题:
6、
生命之树
在X森林里,上帝创建了生命之树。
他给每棵树的每个节点(叶子也称为一个节点)上,都标了一个整数,代表这个点的和谐值。
上帝要在这棵树内选出一个非空节点集S,使得对于S中的任意两个点a,b,都存在一个点列 {a, v1, v2, …, vk, b} 使得这个点列中的每个点都是S里面的元素,且序列中相邻两个点间有一条边相连。
在这个前提下,上帝要使得S中的点所对应的整数的和尽量大。
这个最大的和就是上帝给生命之树的评分。
经过atm的努力,他已经知道了上帝给每棵树上每个节点上的整数。但是由于 atm 不擅长计算,他不知道怎样有效的求评分。他需要你为他写一个程序来计算一棵树的分数。
「输入格式」
第一行一个整数 n 表示这棵树有 n 个节点。
第二行 n 个整数,依次表示每个节点的评分。
接下来 n-1 行,每行 2 个整数 u, v,表示存在一条 u 到 v 的边。由于这是一棵树,所以是不存在环的。
「输出格式」
输出一行一个数,表示上帝给这棵树的分数。
「样例输入」
5
1 -2 -3 4 5
4 2
3 1
1 2
2 5
「样例输出」
8
「数据范围」
对于 30% 的数据,n <= 10
对于 100% 的数据,0 < n <= 10^5, 每个节点的评分的绝对值不超过 10^6 。
这个问题,,首先是个什么问题???
tip;题目很明显的说这是一棵树了,,而且有n个顶点,就是接下来有n-1行,因为一棵树有n个顶点,就会有n-1条边的。注意啊,这里知道是树思路就清晰很多了
树形dp我也真是666了
第一种呢,暴力:枚举所有的子集,然后每个子集用dfs都去看是否能够达到所有点都能联通
第二种,比较神奇了,无根树转有根树的递归
首先,无根树转化为有根树,在每一个有根树中,这颗树的子树如何加和大于0,那就会对他产生正向的影响,如果小于0,那就不要那棵树了,但是这里系统的想一下分成的情况:1,要哪个根,前提是那个根是大于0的,那这个根下的所有子树就开始递归就好了 2,不要那个根,没有那个根就感觉变成了森林一样,,在所有森林中找个最大就出来了,同样每课小树都用递归就好了。。神奇的地方在这里:::无根树变有根树,每次选不同的点起始结果是一样的。最终结果是一样的。
但是这里的递归,因为一直递归到了叶子节点,然后从叶子开始计数,所有就相当于一个记忆性的东西了,要不要再转成一个树状dp都可以
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class test6{
static int w[];
static List<Integer> []g;
static int n;
static int ans = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
g = new ArrayList[n+1];
initG();//list数组里每一个都要初始化一下称为一个小的list,不然不能用
w = new int[n+1];
for(int i =1;i<=n;i++){
w[i] = sc.nextInt();
}
for(int i=0;i<n-1;i++){
int a = sc.nextInt();
int b = sc.nextInt();//下来就用邻接表来存吧,起始就是list,跟他连,被连的就是childrena
g[a].add(b);
g[b].add(a);
}
dfs(1,0);
System.out.println(ans);
}
static void dfs(int u,int fa){
for(int i = 0;i<g[u].size();i++){
Integer child = g[u].get(i);
if(child==fa) continue;//这是啥,就这一行,没有他就全报stackoverflow!!!因为会死循环的!!
dfs(child,u);
if(w[child]>0){
w[u]+=w[child];//这儿比较巧妙,因为直接就存在了w[i]那个数组,因为这里dfs会一下子扎到最根处,也就是一直到最后的叶子节点,这里如果u加叶子节点大于0,那就要他,直接写到他那里就可以了
}
if(w[u]>ans){
ans = w[u];
}
}
}
static void initG(){
for(int i=0;i<n+1;i++){
g[i] = new ArrayList<Integer>();
}
}
}
代码有一个小小的问题,就是应该把int改成long,但是我不知道为啥,明明数据范围也只到10^5,而引用一个大佬说的话:long型数据存储的数范围广而大 我给你举个例子
比方说 int只能存215612316这么大的数 long就可以存 121132131546523123156123这么大的数
?????为什么呀
第三种:这种是我能懂的办法无疑了,直接把当成图来做了
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class test6{
static int w[];
static List<Integer> []g;
static int n;
static int ans = 0;
static int [][]arr;
static boolean vis[];
static int max = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
arr = new int[n+1][n+1];
w = new int[n+1];
vis = new boolean[n+1];
for(int i =1;i<=n;i++){
w[i] = sc.nextInt();
}
for(int i=0;i<n-1;i++){
int a = sc.nextInt();
int b = sc.nextInt();//下来就用邻接表来存吧,起始就是list,跟他连,被连的就是childrena
arr[a][b] = 1;
arr[b][a] =1;
}
dfs(1);
System.out.println(max);
}
static void dfs(int m ){
vis[m] = true;
for(int i=1;i<=n;i++){
if(vis[i] ==false && arr[m][i] !=0){
dfs(i);
if(w[m]<(w[m]+w[i])){
w[m] = w[m]+w[i];
}
max = Math.max(max,w[m]);
}
}
}
static void initG(){
for(int i=0;i<n+1;i++){
g[i] = new ArrayList<Integer>();
}
}
}
第四种:树形dp
首先,树形dp是啥意思嘞??
先来一道例题:
二叉苹果树,
然后再写树形dp的代码,,,这里 我还没有看懂,,,,,