重建道路
题目描述
一场可怕的地震后,人们用 个牲口棚(编号 )重建了农夫 John 的牧场。由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的。因此,牧场运输系统可以被构建成一棵树。
John 想要知道另一次地震会造成多严重的破坏。有些道路一旦被毁坏,就会使一棵含有 个牲口棚的子树和剩余的牲口棚分离,John 想知道这些道路的最小数目。
输入格式
第一行两个整数, 和 。
第二行到第 行,每行两个整数 和 ,表示节点 是节点 的父节点。牧场运输系统可以被构建成一棵以 1 号节点为根的树
输出格式
单独一行,包含一旦被破坏将分离出恰含 个节点的子树的道路的最小数目。
样例 #1
样例输入 #1
11 6
1 2
1 3
1 4
1 5
2 6
2 7
2 8
4 9
4 10
4 11
样例输出 #1
2
提示
样例解释
如果道路 和 被破坏,含有节点()的子树将被分离出来。
限制与约定
,,保证给出的是一棵树。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=201;
struct Edge{
int to,next;
}e[N*2];
int du[N],a[N],dp[N][N];
int n,k,res=INF,EdgeCnt=0;
void addedge(int u,int v){
int p=++EdgeCnt;
e[p].to=v;e[p].next=a[u];
a[u]=p;
}
void dfs(int u,int fa){
dp[u][1]=du[u];
for (int p=a[u];p;p=e[p].next){
int v=e[p].to;
if (v!=fa){
dfs(v,u);
for (int j=k;j>=1;j--)
for (int k=1;k<=j;k++)
dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]-2);
}
}
res=min(res,dp[u][k]);
}
int main(){
scanf("%d%d",&n,&k);
memset(dp,0x3f,sizeof(dp));
for (int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
du[u]++;du[v]++;
}
dfs(1,0);
printf("%d",res);
return 0;
}
10