/*
问题描述:给定n个点的树,最少删多少边,会有棵p个节点的树
dp[i][j]代表以i为根(包含i),共j个节点需要切断的路的数量
dp[i][j+k]=min(f[i][j+k],f[i.son[t]][k])(t为i的孩子)
树形DP+背包
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define MAXSIZE 505000
#define sf scanf
#define pf printf
#define __int64 long long
#define INF 0xfffffff
using namespace std;
vector<int> t[300];
int dp[300][300],vis[200];
int n,p;
void DFS(int r)
{
int i,j,k;
int size=t[r].size();
for( i=0; i<size; i++)
{
DFS(t[r][i]);
}
dp[r][1]=t[r].size();
for(i=0; i<size; i++)
{
for( k=p-1; k>=1; k--)
{
if(dp[r][k]<INF)
{
for(j=1; j+k<=p; j++)
{
if(dp[t[r][i]][j]<INF)
{
dp[r][k+j]=min(dp[r][k+j],dp[t[r][i]][j]+dp[r][k]-1);
//cout<<dp[r][k+j]<<endl;
}
}
}
}
}
return ;
}
int main()
{
while(~sf("%d%d",&n,&p))
{
int u,v;
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
dp[i][j]=INF;
for(int i=0; i<=n; i++)
{
t[i].clear();
vis[i]=0;
}
for(int i=1; i<n; i++)
{
sf("%d%d",&u,&v);
t[u].push_back(v);
vis[v]=1;
}
for(int i=1; i<=n; i++)
{
if(vis[i]==0)
{
DFS(i);
break;
}
}
int ant=dp[1][p];
for(int i=2; i<=n; i++)
{
ant=min(ant,dp[i][p]+1);
}
cout<<ant<<endl;
}
}
poj 1947 Rebuilding Roads(树形DP)
最新推荐文章于 2020-10-14 21:10:18 发布