小美在观察一棵美丽的无根树。
小团问小美:“小美,我考考你,如果我选一个点为根,你能不能找出子树大小不超过K的前提下,子树内最大值和最小值差最大的子树的根是哪个点?多个点的话你给我编号最小的那个点就行了。”
小美思索一番,说这个问题难不倒他。
小美在观察一棵美丽的无根树。
小团问小美:“小美,我考考你,如果我选一个点为根,你能不能找出子树大小不超过K的前提下,子树内最大值和最小值差最大的子树的根是哪个点?多个点的话你给我编号最小的那个点就行了。”
小美思索一番,说这个问题难不倒他。
第一行两个正整数N和K,表示全树有N个节点,要求子树大小不超过K。
第二行是N个正整数空格分隔,表示每个点的点权。以点编号从1到N的顺序给出点权。
接下来N-1行每行两个正整数表示哪两个点之间有边相连。
最后一行一个正整数root表示小团所选的根节点编号为root。
一行,一个正整数,含义如问题描述,输出在子树大小不超过K的前提下,子树内最大值和最小值差最大的子树的根的编号
5 2 1 3 2 4 5 1 2 2 3 3 4 4 5 3
2
对于30%的数据点有
对于100%的数据点有
各点上的权值有
,对于K有
import java.util.*;
public class Main{
static int max=0,index=0;//最大差值,最大差值对应的最小编号
static int[][] dp;//dp[i][0/1/2]i为根对应的最大值、最小值,节点数量
static int k=0;
public static void main(String[] argvs){
Scanner in=new Scanner(System.in);
int n=in.nextInt();
k=in.nextInt();
int[] v=new int[n+1];
dp=new int[n+1][3];
for(int i=1;i<=n;i++) {
v[i]=in.nextInt();
//dp[i][1]=Integer.MAX_VALUE;
}
Map<Integer,Set<Integer>> g=new HashMap<>();
for(int i=0;i<n-1;i++){
int x=in.nextInt(),y=in.nextInt();
Set<Integer> s1=g.computeIfAbsent(x,(a)->new HashSet<>());
Set<Integer> s2=g.computeIfAbsent(y,(a)->new HashSet<>());
s1.add(y);
s2.add(x);
}
int r=in.nextInt();
dfs(r,g,v);
System.out.print(index);
}
public static void dfs(int cur,Map<Integer,Set<Integer>> g,int[] v){
dp[cur][0]=v[cur];
dp[cur][1]=v[cur];
dp[cur][2]=1;
if(!g.containsKey(cur) || g.get(cur).size()==0) return;
Set<Integer> son=g.get(cur);
for(int s:son){
Set<Integer> tmp=g.get(s);
tmp.remove(cur);
dfs(s,g,v);
dp[cur][0]=Math.max(dp[cur][0],dp[s][0]);
dp[cur][1]=Math.min(dp[cur][1],dp[s][1]);
dp[cur][2]+=dp[s][2];
}
int dis=dp[cur][0]-dp[cur][1];
if(dp[cur][2]<=k){
if(dis>max){
max=dis;
index=cur;
}else if(max==dis){
index=Math.min(index,cur);
}
}
}
} import java.util.*;
import java.io.*;
public class Main{
static int poor ; //记录在递归过程中出现的符合要求最大差值
static int index ;//最大差值的下标
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] one = br.readLine().trim().split(" ");
int n = Integer.parseInt(one[0]);
int k = Integer.parseInt(one[1]);
String[] value = br.readLine().trim().split(" ");
Node[] nodes = new Node[n]; //节点数组
//构造节点
for(int i = 0; i < n ; i++){
int num = Integer.parseInt(value[i]);
nodes[i] = new Node(num, i + 1 ,new ArrayList<Node>());
}
//把节点连接起来
for(int i = 0; i < n - 1; i++){
String[] line = br.readLine().trim().split(" ");
int n1 = Integer.parseInt(line[0]);
int n2 = Integer.parseInt(line[1]);
nodes[n1 - 1].list.add(nodes[n2 - 1]);
nodes[n2 - 1].list.add(nodes[n1 - 1]);
}
poor = 0;
index = -1;
Node node = nodes[Integer.parseInt(br.readLine()) - 1];//根节点
//遍历根节点
for(Node nn : node.list){
dfs(nn, node, k);
}
System.out.println(index);
}
public static Info dfs(Node node,Node father,int k){
int maxS = node.value;
int minS = node.value;
int flo = 1;//node节点中个数,flo = 1 是 node这个1
for(Node n : node.list){//遍历连接点
if(n != father){//父节点不遍历
Info info = dfs(n, node, k);
flo += info.flo;//子树中个数相加
maxS = Math.max(maxS, info.max);
minS = Math.min(minS, info.min);
}
}
//如果节点个数小于等于k,并且最大值和最小值差比最大差大,那么替换
if(flo <= k && poor < maxS - minS){
poor = maxS - minS;
index = node.index;
}
//如果节点个数小于等于k,并且最大值和最小值差等于最大差而且下标更小,那么替换下标
if( flo <= k && poor == maxS - minS && node.index < index){
index = node.index;
}
return new Info(maxS, minS, flo);
}
}
//子树返回的信息
class Info{
int max;//子树中的最大值
int min;//子树中的最小值
int flo;//子树中节点个数(在确定根节点的情况下)
public Info(int max, int min, int flo){
this.max = max;
this.min = min;
this.flo = flo;
}
}
//节点类
class Node{
int value;//权值
int index;//节点的下标
List<Node> list;//连接的点
public Node(int value, int index, List<Node> list){
this.value = value;
this.index = index;
this.list = list;
}
}