UESTC 887 方伯伯的儿童节 --树形DP

定义:

1.dp[u][1]表示u这个点设立糖果发放点且u这棵子树满足条件时的最少糖果点数

2.dp[u][0]表示u这个点不设立发放点且u这棵子树满足条件时的最少糖果点数

设v1,v2……vn为u的子节点,则转移方程:

dp[u][1]= sum(min(dp[vi][1],dp[vi][0]) )+1;

dp[u][0]=sum(dp[vi][1]);

由于还要记录方案数,做一个num[][]数组随着dp[][]一起转移:

num[u][1]表示u这个点设立糖果发放点的最少点数方案。

num[u][0]表示u这个点不设立糖果发放点的最少点数方案。

分三种情况:

1.dp[v][0]<dp[v][1]:  dp[u][1] += dp[v][0]     num[u][1] *= num[v][0]

2.dp[v][0]=dp[v][1]:  dp[u][1] += dp[v][0/1]  num[u][1] *= (num[v][1]+num[v][0])

3.dp[v][0]>dp[v][1]:  dp[u][1] += dp[v][1]     num[u][1] *= num[v][1]

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <vector>

#define Mod 1000000007

using namespace std;

#define N 100007



int dp[N][2],num[N][2];

vector<int> G[N];



void dfs(int u,int fa)

{

    dp[u][0] = 0;

    dp[u][1] = 1;

    num[u][0] = num[u][1] = 1;

    for(int i=0;i<G[u].size();i++)

    {

        int v = G[u][i];

        if(v == fa)

            continue;

        dfs(v,u);

        dp[u][0] += dp[v][1];

        num[u][0] *= num[v][1];   //num[u][0]

        num[u][0] %= SMod;

        if(dp[v][0] < dp[v][1])

        {

            dp[u][1] += dp[v][0];

            num[u][1] *= num[v][0];

        }

        else if(dp[v][0] > dp[v][1])

        {

            dp[u][1] += dp[v][1];

            num[u][1] *= num[v][1];

        }

        else

        {

            dp[u][1] += dp[v][1];

            num[u][1] *= (num[v][0]+num[v][1]);

        }

        num[u][1] %= SMod;   //num[u][1]

    }

}



void init()

{

    for(int i=0;i<=100000;i++)

        G[i].clear();

}



int main()

{

    int t,n,i,x,y;

    scanf("%d",&t);

    while(t--)

    {

        init();

        scanf("%d",&n);

        for(i=0;i<n-1;i++)

        {

            scanf("%d%d",&x,&y);

            G[x].push_back(y);

            G[y].push_back(x);

        }

        dfs(1,-1);

        if(dp[1][0] < dp[1][1])

            printf("%d %d\n",dp[1][0],num[1][0]);

        else if(dp[1][0] > dp[1][1])

            printf("%d %d\n",dp[1][1],num[1][1]);

        else

            printf("%d %d\n",dp[1][1],(num[1][1]+num[1][0])%SMod);

    }

    return 0;

}
View Code

 

你可能感兴趣的:(dp)