poj 1947 简单树形dp building roads
来源:互联网 发布:c语言打印一个三角形 编辑:程序博客网 时间:2024/05/21 19:44
#include<iostream>#include<cstdio>/// 从 一棵树上切去最少的边使其剩余子树里含有 p个节点的子树/// 状态转移方程 : dp[u][j]=max(dp[u][tt]+dp[v][j-tt]-1,dp[u][j]);/// 表示从父节点选取tt个,从孩子节点选取j-tt个的最小值#include<algorithm>#include<cstring>#include<vector>using namespace std;int n,k,dp[152][152],sum[152],vis[152];vector<int>p[152];void dfs(int u,int fa){ int i,j,tt, v; int cnt=p[u].size(); dp[u][1]=cnt; for(i=0; i<cnt; i++) { v=p[u][i]; if(v==fa)continue; dfs(v,u); for(j=k; j>=1; j--) { for(tt=1; tt<=j; tt++) { dp[u][j]=min(dp[u][tt]+dp[v][j-tt]-1,dp[u][j]); } } }}int main(){ while(scanf("%d%d",&n,&k)!=EOF) { int i,j,u,v,ans=1<<29; for(i=0; i<=n; i++) { p[i].clear(); for(j=0; j<=k; j++) { dp[i][j]=1<<29; } } for(i=1; i<n; i++) { cin>>u>>v; p[u].push_back(v); } dfs(1,0); ans=dp[1][k]; for(i=2;i<=n;i++) { ans=min(ans,dp[i][k]+1);///根节点外的子树需要多切去一条与根节点向连接的边 } cout<<ans<<endl; } return 0;}