[poj 1947]树dp+背包问题

题目链接:http://poj.org/problem?id=1947

看了很多题解都是直接一遍dfs就搞定的方法,但是我实在是没看懂那个转移方程。最后在茫茫博客中终于发现了一个有逻辑的方法,但是复杂度好像要高一些,但是还是把这个题过了。http://www.chongchonggou.com/g_91242661.html

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;

const int maxn=155;
vector<int> G[maxn];

const int INF=0x3f3f3f3f;
int dp[2][maxn];
int f[maxn][maxn];
int res[maxn][maxn];

void dfs(int u,int fa)
{
    if (G[u].size()==0)
    {
        f[u][0]=f[u][1]=0;
        if (fa==-1) res[u][0]=res[u][1]=0;
        else res[u][0]=res[u][1]=1;
    }
    else
    {
        for (int i=0;i<G[u].size();i++)
        {
            int v=G[u][i];
            dfs(v,u);
        }
        memset(dp,INF,sizeof(dp));
        dp[0][0]=0;
        for (int i=1;i<=G[u].size();i++)
        {
            for (int j=0;j<=150;j++)
            {
                dp[i&1][j]=INF;
                for (int k=0;k<=j;k++)
                {
                    dp[i&1][j]=min(dp[i&1][j],dp[i&1^1][j-k]+f[G[u][i-1]][k]+(k==0));
                }
            }
        }
        f[u][0]=0;
        if (fa==-1) res[u][0]=0;
        else res[u][0]=1;
        for (int i=1;i<=150;i++) f[u][i]=dp[G[u].size()&1][i-1];
        for (int i=1;i<=150;i++) res[u][i]=f[u][i]+(fa!=-1);
    }
}

int main()
{
    memset(f,INF,sizeof(f));
    memset(res,INF,sizeof(res));
    int n,P;
    scanf("%d%d",&n,&P);
    for (int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
    }
    dfs(1,-1);
    int ans=INF;
    for (int i=1;i<=n;i++) ans=min(ans,res[i][P]);
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2017-08-30 16:17  ACMsong  阅读(168)  评论(0编辑  收藏  举报