特定N点,N-1的关系。建立了一棵树,问至少减去几个边缘节点可以被作为得到P树。树典型DP称号
dp[cur][j] :记录cur节点,为了得到一个j除去该子树的节点的边的最小数目
对当前树的每个子树进行计算
砍掉此子树: dp[cur][j]=dp[cur][j]+1;
不砍掉: for (l=0;l<=j;l++) dp[cur][j]=Min(dp[cur][j],dp[cur][l]+dp[next][j-l]); 枚举从该树中留l个节点其它由新进子树得到的方案的代价 dp[cur][l]+dp[next][j-l];
#include "stdio.h" #include "vector" #include "math.h" #include "string.h" int inf=0x3f3f3f3f; using namespace std; struct node { int fa; vector<int>child; }data[160]; int dp[160][160]; int p; int Min(int a,int b) { if (a<b) return a; else return b; } void dfs(int cur) { int next,i,j,l; dp[cur][1]=0; for (i=0;i<data[cur].child.size();i++) { next=data[cur].child[i]; dfs(next); for (j=p;j>=0;j--) { dp[cur][j]=dp[cur][j]+1; for (l=0;l<=j;l++) dp[cur][j]=Min(dp[cur][j],dp[cur][l]+dp[next][j-l]); } } } int main() { int n,a,b,i,root,ans; while (scanf("%d%d",&n,&p)!=EOF) { memset(dp,inf,sizeof(dp)); memset(data,0,sizeof(data)); for (i=1;i<n;i++) { scanf("%d%d",&a,&b); data[b].fa=a; data[a].child.push_back(b); } for (i=1;i<=n;i++) if (data[i].fa==0) { root=i; break; } dfs(root); ans=dp[root][p]; for (i=1;i<=n;i++) ans=Min(ans,dp[i][p]+1); printf("%d ",ans); } return 0; }
版权声明:本文博客原创文章。博客,未经同意,不得转载。