*******************************bestcoder题解********************************
Cities
选出K个点v1,v2,...vK使得∑Ki=1∑Kj=1dis(vi,vj)最小.
考虑每条边的贡献,一条边会把树分成两部分,若在其中一部分里选择了x个点,则这条边被统计的次数为x*(K-x)*2.
那么考虑dp[u][i]表示在u的子树中选择了i个点的最小代价,有转移dp[u][i]=minKj=0(dp[u][i−j]+dp[v][j]+j∗(K−j)∗2∗wu,v),式子中u为v的父亲,wu,v表示(u,v)这条边的长度.
时间复杂度O(nK^2).
****************************************************************************
1 #include <iostream>
2 #include <cstdio>
3 #include <cstdlib>
4 #include <memory.h>
5 using namespace std;
6 typedef long long LL;
7 const int INF = 0x3fffffff;
8 const LL LINF = INF * 1ll * INF;
9 using namespace std;
10
11 #define MAXN 5005
12
13 struct Edge{
14 int to;
15 int w;
16 int next;
17 };
18
19 LL dp[MAXN][60]; //dp[n][k] 代表第n个结点 有k个结点连通
20 Edge e[MAXN];
21 int head[MAXN];
22 int t;
23 int n,k;
24
25 //适用于正负整数
26 template <class T>
27 inline bool scan_d(T &ret) {
28 char c; int sgn;
29 if(c=getchar(),c==EOF) return 0; //EOF
30 while(c!='-'&&(c<'0'||c>'9')) c=getchar();
31 sgn=(c=='-')?-1:1;
32 ret=(c=='-')?0:(c-'0');
33 while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
34 ret*=sgn;
35 return 1;
36 }
37
38 //取小值给ans
39 LL update(LL &ans,LL temp)
40 {
41 if (ans > temp) ans = temp;
42 }
43
44 void dfs(int u,int fa){
45 for(int i = head[u];~i;i = e[i].next){//注意~运算
46 if(e[i].to == fa) continue; //不再访问父亲结点
47 dfs(e[i].to,u);
48 }
49 for(int i = 0;i <= k;i++) dp[u][i] = LINF; //LINF代表不可达
50 dp[u][1] = 0;
51 for(int i = head[u];!i;i = e[i].next){ //访问当前点u的所有子树
52 if(e[i].to == fa) continue; //不包含父亲结点
53 int v = e[i].to;
54 for(int a = k;a >= 0;a--){ //类似01背包
55 for(int b = 1;a+b <= k;b++){ //因为一条边把树分成两个部分,其中一部分已经访问了a个结点,则另一部分还需访问k-a个结点
56 if(dp[v][b] == LINF) break; //若为LINF则不可达 比如,只有两个子节点,则dp[v][4]就不存在
57 update(dp[u][a+b],dp[u][a] + dp[v][b] + 2ll*b*(k-b)*e[i].w);
58 }
59 }
60 }
61 }
62
63 //建立关于边的临街边
64 void addedge(int from,int to,int w)
65 {
66 e[t].to = to;
67 e[t].w = w;
68 e[t].next = head[from];
69 head[from] = t;
70 t++;
71 }
72
73
74 void process()
75 {
76 int from,target,weight;
77 scan_d(n);
78 scan_d(k);
79 t = 0;
80 memset(head,-1,sizeof(head));
81 for (int i = 1;i < n; ++ i) {
82 scan_d(from);
83 scan_d(target);
84 scan_d(weight);
85 addedge(from,target,weight);
86 addedge(target,from,weight);
87 }
88 dfs(1,-1);
89 LL ans = LINF;
90 for (int i = 1;i <= n; ++ i) {
91 update(ans,dp[i][k]);
92 }
93 cout << ans << endl;
94 }
95
96
97 int main()
98 {
99 int T;
100 cin >> T;
101 while (T--)
102 {
103 process();
104 }
105 return 0;
106 }