标签:io for amp size c poj 关系 dp
给出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\n",ans); } return 0; }
POJ 1947 树形DP入门题,布布扣,bubuko.com
标签:io for amp size c poj 关系 dp
原文地址:http://blog.csdn.net/u011932355/article/details/38371041