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