codeforces1249F. Maximum Weight Subset

https://codeforces.com/contest/1249/problem/F

F. Maximum Weight Subset

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a tree, which consists of nn vertices. Recall that a tree is a connected undirected graph without cycles.

Example of a tree.

Vertices are numbered from 11 to nn. All vertices have weights, the weight of the vertex vv is avav.

Recall that the distance between two vertices in the tree is the number of edges on a simple path between them.

Your task is to find the subset of vertices with the maximum total weight (the weight of the subset is the sum of weights of all vertices in it) such that there is no pair of vertices with the distance kk or less between them in this subset.

Input

The first line of the input contains two integers nn and kk (1≤n,k≤2001≤n,k≤200) — the number of vertices in the tree and the distance restriction, respectively.

The second line of the input contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1051≤ai≤105), where aiai is the weight of the vertex ii.

The next n−1n−1 lines contain edges of the tree. Edge ii is denoted by two integers uiui and vivi — the labels of vertices it connects (1≤ui,vi≤n1≤ui,vi≤n, ui≠viui≠vi).

It is guaranteed that the given edges form a tree.

Output

Print one integer — the maximum total weight of the subset in which all pairs of vertices have distance more than kk.

Examples

input

Copy

5 1
1 2 3 4 5
1 2
2 3
3 4
3 5

output

Copy

11

input

Copy

7 2
2 1 2 1 2 1 1
6 4
1 5
3 1
2 3
7 5
7 4

output

Copy

4

dp要加一维来记录距离。参考 :https://codeforces.com/blog/entry/70822

import java.util.*;
import java.io.*;

public class Main {
	public static void main(String args[]) {new Main().run();}

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		work();
		out.flush();
	}
	long mod=1000000007;
	long gcd(long a,long b) {
		return b==0?a:gcd(b,a%b);
	}
	int[] weight;
	ArrayList<Integer>[] graph;
	int[][] dp;
	int k;
	void work() {
		int n=in.nextInt();
		k=in.nextInt();
		dp=new int[n][k+1];//节点node,距离最近的选择点距离至少为d时的 子树权值和的最大值
		weight=new int[n];
		for(int i=0;i<n;i++)weight[i]=in.nextInt();
		graph=(ArrayList<Integer>[])new ArrayList[n];
		for(int i=0;i<n;i++) {
			graph[i]=new ArrayList<>();
		}
		for(int i=0;i<n-1;i++) {
			int n1=in.nextInt()-1;
			int n2=in.nextInt()-1;
			graph[n1].add(n2);
			graph[n2].add(n1);
		}
		dfs(0,new boolean[n]);
		out.println(dp[0][0]);
	}
	private void dfs(int node, boolean[] vis) {
		vis[node]=true;
		ArrayList<Integer> list=new ArrayList<>();
		for(int nn:graph[node]) {
			if(!vis[nn]) {
				dfs(nn,vis);
				list.add(nn);
			}
		}
		for(int i=0;i<=k;i++) {
			if(i==0) {
				dp[node][0]=weight[node];
				for(int nn:list) {
					dp[node][0]+=dp[nn][k];
				}
			}else{
				int v1=i-1;
				int v2=Math.max(v1,k-1-v1);
				int sum=0;
				int ret=0;
				for(int nn:list) {
					sum+=dp[nn][v2];
				}
				for(int nn:list) {
					sum-=dp[nn][v2];
					sum+=dp[nn][v1];//当v1点不选的情况肯定不是候选者
					ret=Math.max(ret, sum);
					sum+=dp[nn][v2];
					sum-=dp[nn][v1];
				}
				dp[node][i]=ret;
			}
		}
		for(int i=k-1;i>=0;i--) {
			dp[node][i]=Math.max(dp[node][i], dp[node][i+1]);
		}
	}
}



class FastReader
{
	BufferedReader br;
	StringTokenizer st;

	public FastReader()
	{
		br=new BufferedReader(new InputStreamReader(System.in));
	}

	public String next() 
	{
		if(st==null || !st.hasMoreElements())
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

	public int nextInt() 
	{
		return Integer.parseInt(next());
	}

	public long nextLong()
	{
		return Long.parseLong(next());
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值