zoukankan      html  css  js  c++  java
  • 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
    ",dp[1][0],num[1][0]);
            else if(dp[1][0] > dp[1][1])
                printf("%d %d
    ",dp[1][1],num[1][1]);
            else
                printf("%d %d
    ",dp[1][1],(num[1][1]+num[1][0])%SMod);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    算法基础<七> 加权有向图
    union 分页/group/join 复杂查询(.net core/framework)
    扩展Elasticsearch客户端简化ES查询(.net core/framework)
    对EF Core进行扩展使支持批量操作/复杂查询
    Grpc对象转proto代码工具
    扩展ADO.net实现对象化CRUD(.net core/framework)
    Sublime Text 4 破解笔记
    python三元表达式(三目运算符)的坑
    xaf-常见问题解答
    xaf.blazor中如何开启诊断按钮
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3762757.html
Copyright © 2011-2022 走看看