Given a graph with N vertices (labeled 1 to N). The graph is connected, undirected and acyclic, and also known as an "unrooted tree". Each vertex has a weight, which is an integer. The total weight of a tree, is the summation of the weight of all its vertices.
Follow the instruction below to "cut the tree" exactly K times:
(1) Choose an edge of the tree, and remove it.
(2) Choose and discard one of the two divided parts of the graph we get.
(3) Get a new unrooted tree.
Now you are asked to calculate, after all those done, the minimal and maximal weight of the tree we finally get.
Input
Mutiple test cases, process to the end of file.
Each test case consists of three parts.
First part, a single line with two integers N (1<=N<=1000) and K (0<=K<=20, K<N).
Second part, a single line with N integers, the weight of vertices labeled 1 to N. The weight is in range [-1000,1000].
Third part, N-1 lines, each line with two integers X and Y represents an edge between vertex X and vertex Y.
Output
For each test case, output one line with two integers, the minimal and maximal weight of the tree we finally get.
Sample Input
2 1 -1 1 1 2 6 0 -3 1 -2 3 4 0 1 2 1 3 2 4 3 5 3 6 6 1 -3 1 -2 3 4 0 1 2 1 3 2 4 3 5 3 6
Sample Output
-1 1 3 3 -1 4
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;
int n,m,ans,cnt,tot,flag;
int pp[maxn],cost[maxn],num[maxn],dp[maxn][25];
struct Node
{
int v,w,next;
} edge[MAXN];
void addedge(int u,int v,int w)
{
cnt++;
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=pp[u];
pp[u]=cnt;
}
void dfs(int u,int pre)
{
int i,j,k,v,t;
dp[u][0]=cost[u];
num[u]=0;
for(i=1; i<=m; i++)
{
dp[u][i]=INF;
}
for(i=pp[u]; i; i=edge[i].next)
{
v=edge[i].v;
if(v==pre) continue ;
dfs(v,u);
num[u]+=num[v]+1; // 以v为根的边及u-v这条边
for(j=m; j>=0; j--)
{
dp[u][j]+=dp[v][0]; // 将dp[v][0]先强制转移过来
for(k=1; k<=j; k++) // k!=0 dp[v][0]不转移两次
{ // 如果都在这里转移的话会产生 dp[u][j]转移不对的情况 dp[v][0]>0的话dp[u][j]就会不要它了
dp[u][j]=min(dp[u][j],dp[v][k]+dp[u][j-k]);
}
for(k=1; k<=num[v]+1&&k<=j; k++)
{
dp[u][j]=min(dp[u][j],dp[u][j-k]);
}
}
}
}
int solve()
{
int i,j,t;
dfs(1,0);
ans=dp[1][m];
for(i=2; i<=n; i++)
{
for(j=1; j<=n-1-num[i]&&j<=m; j++) // 在除了以i为根之外的边上砍j刀(j至少为1)
{
ans=min(ans,dp[i][m-j]);
}
}
return ans;
}
int main()
{
int i,j,t,u,v;
while(~scanf("%d%d",&n,&m))
{
for(i=1; i<=n; i++)
{
scanf("%d",&cost[i]);
}
cnt=0;
memset(pp,0,sizeof(pp));
for(i=1; i<n; i++)
{
scanf("%d%d",&u,&v);
addedge(u,v,0);
addedge(v,u,0);
}
int x=solve();
for(i=1; i<=n; i++)
{
cost[i]=-cost[i];
}
int y=-solve();
printf("%d %d\n",x,y);
}
return 0;
}
/*
6 2
-3 1 -2 3 4 0
1 2
1 3
2 4
3 5
3 6
6 3
-3 1 -2 3 4 0
1 2
1 3
2 4
3 5
3 6
6 4
-3 1 -2 3 4 0
1 2
1 3
2 4
3 5
3 6
6 5
-3 1 -2 3 4 0
1 2
1 3
2 4
3 5
3 6
-5 4
-5 4
-5 4
-3 4
*/