The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The cows didn't have time to rebuild any extra roads, so now there is exactly one way to get from any given barn to any other barn. Thus, the farm transportation system can be represented as a tree.
Farmer John wants to know how much damage another earthquake could do. He wants to know the minimum number of roads whose destruction would isolate a subtree of exactly P (1 <= P <= N) barns from the rest of the barns.
Input
* Line 1: Two integers, N and P
* Lines 2..N: N-1 lines, each with two integers I and J. Node I is node J's parent in the tree of roads.
Output
A single line containing the integer that is the minimum number of roads that need to be destroyed for a subtree of P nodes to be isolated.
Sample Input
11 6
1 2
1 3
1 4
1 5
2 6
2 7
2 8
4 9
4 10
4 11
Sample Output
2
题意就是求出从原先树上分割出包含p个点的子树的最小花费
我们随便找一个点作为根节点。然后树形DP即可。
DP[i][j]表示以i节点为根的子树包含j个点的最小花费是多少
dp初始化为
for(int i=1;i<=n;i++)
dp[i][1]=du[i];
du数组表示每个节点的度数。
状态转移方程为
for(int j=p;j>=2;j--)
{
for(int k=j-1;k>=1;k--)
{
dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]-2);// -2是为了除去重复的边
}
}
应该可以很容易的看出 这是一个01背包问题的状态转移方程。
#include <string>
#include<string.h>
#include<vector>
#include<queue>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<cstdio>
#include<iostream>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fuck(x) cout<<x<<endl
#define mem(a,b) memset(a,b,sizeof a)
const int MAX=1000;
class e
{
public:
int u,v,next;
};
e edge[MAX<<1];
int head[MAX];
int tot=0;
void add(int u,int v)
{
edge[tot].u=u,edge[tot].v=v,edge[tot].next=head[u],head[u]=tot++;
}
void init()
{
tot=0;
mem(head,-1);
}
int du[MAX];
int dp[MAX][MAX];
int n,p;
void init2()
{
mem(dp,0x3f);
mem(du,0);
}
void dfs(int u,int per)
{
dp[u][1]=du[u];
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==per)
continue;
dfs(v,u);
for(int j=p;j>=2;j--)
{
for(int k=j-1;k>=1;k--)
{
dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]-2);
}
}
}
}
int main()
{
while(~scanf("%d %d",&n,&p))
{
init();
init2();
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
du[u]++;
du[v]++;
}
for(int i=1;i<=n;i++)
dp[i][1]=du[i];
dfs(1,-1);
int ans=0x3f3f3f3f;
for(int i=1;i<=n;i++)
ans=min(dp[i][p],ans);
cout<<ans<<endl;
}
}