poj 1947 Rebuilding Roads(树形DP)
来源:互联网 发布:淘宝批发市场 编辑:程序博客网 时间:2024/05/16 09:09
/*问题描述:给定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 0xfffffffusing 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; }}