Codeforces1223E. Paint the Tree

https://codeforces.com/contest/1223/problem/E

You are given a weighted tree consisting of nn vertices. Recall that a tree is a connected graph without cycles. Vertices uiui and vivi are connected by an edge with weight wiwi.

Let's define the kk-coloring of the tree as an assignment of exactly kk colors to each vertex, so that each color is used no more than two times. You can assume that you have infinitely many colors available. We say that an edge is saturated in the given kk-coloring if its endpoints share at least one color (i.e. there exists a color that is assigned to both endpoints).

Let's also define the value of a kk-coloring as the sum of weights of saturated edges.

Please calculate the maximum possible value of a kk-coloring of the given tree.

You have to answer qq independent queries.

Input

The first line contains one integer qq (1≤q≤5⋅1051≤q≤5⋅105) – the number of queries.

The first line of each query contains two integers nn and kk (1≤n,k≤5⋅1051≤n,k≤5⋅105) — the number of vertices in the tree and the number of colors to assign to each vertex, respectively.

Each of the next n−1n−1 lines describes an edge of the tree. Edge ii is denoted by three integers uiui, vivi and wiwi (1≤ui,vi≤n1≤ui,vi≤n, ui≠viui≠vi, 1≤wi≤1051≤wi≤105) — the labels of vertices it connects and the weight of the edge. It is guaranteed that the given edges form a tree.

It is guaranteed that sum of all nn over all queries does not exceed 5⋅1055⋅105.

Output

For each query print one integer — the maximum value of a kk-coloring of the given tree.

Example

input

Copy

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

output

Copy

8
14

Note

The tree corresponding to the first query in the example:

One of the possible kk-colorings in the first example: (1),(1),(2),(2)(1),(1),(2),(2), then the 11-st and the 33-rd edges are saturated and the sum of their weights is 88.

 

One of the possible kk-colorings in the second example: (1,2),(1,3),(2,4),(5,6),(7,8),(3,4),(5,6)(1,2),(1,3),(2,4),(5,6),(7,8),(3,4),(5,6), then the 11-st, 22-nd, 55-th and 66-th edges are saturated and the sum of their weights is 1414.

 

容易得出一维情况。又可以得出二维情况。求出当前节点和其之后的最大贡献值,分两种情况:当前节点与其父节点的边是否选择。每个节点最多连选择K条边,所以两种情况下,后面返回的节点 最多选择K,和K-1条边。

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(){
		int q=in.nextInt();
		for(int i=0;i<q;i++) {
			out.println(work());
		}
		out.flush();
	}
	long mod=1000000007;
	long gcd(long a,long b) {
		return b==0?a:gcd(b,a%b);
	}
	ArrayList<int[]>[] graph;
	int k=0;
	long work() {
		int n=in.nextInt();
		this.k=in.nextInt();
		graph=(ArrayList<int[]>[])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;
			int w=in.nextInt();
			graph[n1].add(new int[] {n2,w});
			graph[n2].add(new int[] {n1,w});
		}
		long[] ret=dfs(0,new boolean[n],0);
		return Math.max(ret[0],ret[1]);
	}
	返回值:当前节点和其之后的最大贡献值,分两种情况:当前节点与其父节点的边是否选择。每个节点最多连选择K条边
	long[] dfs(int node,boolean[] vis,int weight){
		vis[node]=true;
		PriorityQueue<Long> pq=new PriorityQueue<>();
		long[] ret=new long[2];
		long sum=0;
		for(int[] g:graph[node]) {
			int nn=g[0];
			int w=g[1];
			if(!vis[nn]) {
				long[] d=dfs(nn,vis,w);
				sum+=d[0];
				if(d[1]-d[0]>0){
					pq.add(d[1]-d[0]);
				}
				if(pq.size()>k)pq.poll();
			}
		}
		ret[0]=sum;
		ret[1]=sum+weight;
		if(pq.size()==k)ret[1]-=pq.peek();//ret[1]后面最多选(k-1)条,有连接
		while(pq.size()>0) {
			long p=pq.poll();
			ret[0]+=p;
			ret[1]+=p;
		}
		return ret;
	}
}



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());
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值