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;}