Language:
Rebuilding Roads
Description
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 Hint
[A subtree with nodes (1, 2, 3, 6, 7, 8) will become isolated if roads 1-4 and 1-5 are destroyed.]
|
//dp[k][j]表示将k节点作为一颗子树的根拥有j个节点需要减去的边数
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=155;
int n,p;
int dp[maxn][maxn];
vector<int>vec[maxn];
void init(){
for(int i=1;i<=n;++i){
vec[i].clear();
}
}
void dfs(int k){
for(int i=0;i<vec[k].size();++i){
dfs(vec[k][i]);
for(int j=p;j>=1;--j){
for(int v=1;v<j;++v){
dp[k][j]=min(dp[k][j],dp[vec[k][i]][v]+dp[k][j-v]-1);//因为在计算dp[k][j-v]时是将k与vec[k][i]减去的但因为计算dp[k][j]不需要减去此边因此要再+1
}
}
}
}
int main()
{
int i,j,k;
while(scanf("%d%d",&n,&p)!=EOF){
int a,b;init();
for(i=0;i<n-1;++i){
scanf("%d%d",&a,&b);
vec[a].push_back(b);
}
memset(dp,0x3f,sizeof(dp));
for(i=1;i<=n;++i){
dp[i][1]=vec[i].size();
}
dfs(1);
int ans=dp[1][p];
for(i=2;i<=n;++i){
ans=min(ans,dp[i][p]+1);//需要将子树的根与数相连的边减去
}
printf("%d\n",ans);
}
return 0;
}