Codeforces 461B Appleman and Tree(树形dp)

题目链接:Codeforces 461B Appleman and Tree

题目大意:一棵树,以0节点为根节点,给定每个节点的父亲节点,以及每个点的颜色(0表示白色,1表示黑色),切断这棵树的k条边,使得树变成k+1个联通分量,保证每个联通分量有且仅有1个黑色节点。问有多少种分割方法。

解题思路:树形dp,dp[i][0]和dp[i][1]分别表示子树一下的分割方法中,i节点所在联通块不存在黑节点和已经存在一个黑节点的方案数。

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
typedef long long ll;
const int MOD = 1e9+7;
const int maxn = 1e5+5;

int N, v[maxn];
ll dp[maxn][2];
vector<int> g[maxn];

void init () {
    memset(dp, 0, sizeof(dp));

    int x;
    scanf("%d", &N);
    for (int i = 1; i < N; i++) {
        scanf("%d", &x);
        g[x].push_back(i);
    }

    for (int i = 0; i < N; i++)
        scanf("%d", &v[i]);
}

ll pow_mod (ll x, int n, ll mod) {
    ll ret = 1;
    while (n) {
        if (n&1)
            ret = ret * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return ret;
}

ll inv (ll x) {
    if (x == 0)
        return 1;
    return pow_mod(x, MOD-2, MOD);
}

void solve (int u) {
    if (g[u].size() == 0) {
        dp[u][v[u]] = 1;
        return;
    }

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

    if (v[u]) {
        dp[u][0] = 0;
        ll& ans = dp[u][1];
        ans = 1;

        for (int i = 0; i < g[u].size(); i++) {
            int k = g[u][i];
            ans = ans * (dp[k][1] + dp[k][0]) % MOD;
        }
    } else {
        dp[u][1] = 0;
        ll& ans = dp[u][0];
        ans = 1;

        for (int i = 0; i < g[u].size(); i++) {
            int k = g[u][i];
            ans = ans * (dp[k][0] + dp[k][1]) % MOD;
        }

        for (int i = 0; i < g[u].size(); i++) {
            int k = g[u][i];
            dp[u][1] += ans * inv(dp[k][0] + dp[k][1]) % MOD * dp[k][1] % MOD;
            dp[u][1] %= MOD;
        }
    }
    //printf("%d %d %d\n", u, dp[u][0], dp[u][1]);
}

int main () {
    init();
    solve(0);
    printf("%lld\n",  dp[0][1] % MOD);
    return 0;
}
时间: 2024-10-14 05:02:02

Codeforces 461B Appleman and Tree(树形dp)的相关文章

Codeforces 461B. Appleman and Tree[树形DP 方案数]

B. Appleman and Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other vertices are color

Codeforces 461B Appleman and Tree(木dp)

题目链接:Codeforces 461B Appleman and Tree 题目大意:一棵树,以0节点为根节点,给定每一个节点的父亲节点,以及每一个点的颜色(0表示白色,1表示黑色),切断这棵树的k条边,使得树变成k+1个联通分量.保证每一个联通分量有且仅有1个黑色节点.问有多少种切割方法. 解题思路:树形dp,dp[i][0]和dp[i][1]分别表示子树一下的切割方法中,i节点所在联通块不存在黑节点和已经存在一个黑节点的方案数. #include <cstdio> #include &l

CF 461B Appleman and Tree 树形DP

Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other vertices are colored white. Consider a set consisting of k (0 ≤ k < n) edges of Appleman's tree. If Appleman deletes these edges from the tree, then

Codeforces 462D Appleman and Tree 树形dp

题目链接:点击打开链接 题意: 给定n个点的树, 0为根,下面n-1行表示每个点的父节点 最后一行n个数 表示每个点的颜色,0为白色,1为黑色. 把树分成若干个联通块使得每个联通块有且仅有一个黑点,问有多少种分法(结果mod1e9+7) 思路: 树形dp,每个点有2个状态,已经归属于某个黑点和未归属于某个黑点. #include <cstdio> #include <vector> #include <iostream> using namespace std; #de

codeforces 416B. Appleman and Tree 树形dp

题目链接 Fill a DP table such as the following bottom-up: DP[v][0] = the number of ways that the subtree rooted at vertex v has no black vertex. DP[v][1] = the number of ways that the subtree rooted at vertex v has one black vertex. The recursion pseudo

Codeforces Round #263 (Div. 2) D. Appleman and Tree 树形dp

链接: http://codeforces.com/contest/462/problem/D 题意: 给定n个点的树, 0为根,下面n-1行表示每个点的父节点 最后一行n个数 表示每个点的颜色,0为白色,1为黑色. 把树分成若干个联通块使得每个联通块有且仅有一个黑点,问有多少种分法(结果mod1e9+7) 题解: 树形dp,每个点有2个状态,已经归属于某个黑点和未归属于某个黑点. 代码: 31 int n; 32 int x[MAXN]; 33 VI G[MAXN]; 34 ll dp[MAX

codeforces 461B Appleman and Tree

题意:问你将含有黑白点的无向树使得每个子树中只有一个黑点的方法数. 解题思路:树形dp,dp[i][0/1] 表示 第i 个节点的联通图中是否有 1个黑点的种类数. 解题代码: 1 // File Name: 461c.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月11日 星期三 10时53分22秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8

【树形DP】CODEFORCES 461B Appleman and Tree

通道 题意:一棵树上有K个黑色节点,剩余节点都为白色,将其划分成K个子树,使得每棵树上都只有1个黑色节点,共有多少种划分方案 思路:dp[i][0]和dp[i][1]分别表示i子树所在联通块不存在黑节点和已经存在一个黑节点的方案数 代码: #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<ma

CodeForces 461B Appleman and Tree:Tree dp

题目链接:http://codeforces.com/problemset/problem/461/B 题意: 给你一棵树(编号从0到n-1,0为根节点),每个节点有黑白两种颜色,其中黑色节点有k+1个. 现在让你删掉k条边,使得这棵树变成k+1个连通块,并且要保证每个连通块中有且仅有一个黑色节点. 问你删边的方案有多少种. 题解: 表示状态: dp[i][0/1] = numbers 表示在节点i所在的连通块中有(1)或没有(0)黑色节点时,节点i的子树的删边方法数 因为总要保证每个连通块中有