POJ1947:Rebuilding Roads(树形DP)

来源:互联网 发布:js 有没有trim函数 编辑:程序博客网 时间:2024/04/28 22:19

思路是参考别人而写的!按照别人思路,敲了一遍代码!题意:给出n,p,一共有n个节点,要求最少减去最少的边是多少,剩下p个节点http://blog.csdn.net/libin56842/article/details/9834101 (思路转自别人)思路:典型的树形DP,dp[s][i]:记录s结点,要得到一棵j个节点的子树去掉的最少边数考虑其儿子k1)如果不去掉k子树,则dp[s][i] = min(dp[s][j]+dp[k][i-j]) 0 <= j <= i2)如果去掉k子树,则dp[s][i] = dp[s][i]+1总的为dp[s][i] = min (min(dp[s][j]+dp[k][i-j]) , dp[s][i]+1 )
本人代码:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>using namespace std;int dp[155][155],n,m,num;vector<int>id[155];void dfs(int p,int t){    if(id[p].size()==1&&t!=-1) return ;    for(int i=0;i<id[p].size();i++)    {        int k=id[p][i];        if(k==t) continue;        dfs(k,p);        for(int j=m;j>=1;j--)        {            int sum=dp[p][j]+1;            for(int tt=1;tt<j;tt++)                sum=min(dp[p][tt]+dp[k][j-tt],sum);            dp[p][j]=sum;            //printf("%d %d %d\n",p,j,dp[p][j]);        }    }}void solve(int p,int t){    if(id[p].size()==1&&t!=-1)    {        if(t!=-1) num=min(dp[p][m]+1,num);        else num=min(dp[p][m],num);        return ;    }    for(int i=0;i<id[p].size();i++)    {        int k=id[p][i];        if(k==t) continue;        if(t!=-1) num=min(dp[p][m]+1,num);        else num=min(dp[p][m],num);        solve(k,p);    }}int main(){    int i,j,a,b;    while(scanf("%d %d",&n,&m)!=EOF)    {        if(n==1)        {            printf("0\n");            continue;        }        for(i=0;i<=n;i++)            id[i].clear();        num=99999999;        for(i=1;i<n;i++)        {            scanf("%d %d",&a,&b);            id[a].push_back(b);            id[b].push_back(a);        }        for(i=1;i<=n;i++)        {            for(j=1;j<=m;j++)            {                if(j!=1) dp[i][j]=99999999;                else dp[i][1]=0;            }        }        dfs(1,-1);        solve(1,-1);        printf("%d\n",num);    }    return 0;}


0 0