CodeForces - 461B Appleman and Tree

题意:

给定一棵有 n n 个结点的树,结点颜色为白或者黑,求删去 k ( 0 k < n ) k(0 \leq k \lt n) 条边后,各联通块恰含有一个黑色结点的方案数。 ( n 1 0 5 ) (n \leq 10^5)

链接:

https://vjudge.net/problem/CodeForces-461B

解题思路:

树形 d p dp d p [ u ] [ 0 ] dp[u][0] 表示以 u u 为根的联通块没有黑色结点, d p [ u ] [ 1 ] dp[u][1] 表示有黑色结点。对待加入的子树逐一合并,讨论连接边是否删去。

参考代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

vector<int> G[maxn];
int a[maxn]; ll dp[maxn][2];
int n;

void dfs(int u, int f){

    dp[u][0] = dp[u][1] = 0, dp[u][a[u]] = 1;
    for(auto &v : G[u]){

        if(v == f) continue;
        dfs(v, u);
        ll tp[2] = {dp[u][0], dp[u][1]};
        dp[u][0] = tp[0] * dp[v][0] + tp[0] * dp[v][1], dp[u][0] %= mod;
        dp[u][1] = tp[0] * dp[v][1] + tp[1] * dp[v][0] + tp[1] * dp[v][1], dp[u][1] %= mod;
    }
}

int main(){

    ios::sync_with_stdio(0); cin.tie(0);
    cin >> n;
    for(int i = 2; i <= n; ++i){

        int u; cin >> u; ++u;
        G[i].pb(u), G[u].pb(i);
    }
    for(int i = 1; i <= n; ++i) cin >> a[i];
    dfs(1, 0);
    cout << dp[1][1] << endl;
    return 0;
}
发布了55 篇原创文章 · 获赞 0 · 访问量 1242

猜你喜欢

转载自blog.csdn.net/weixin_44059127/article/details/104086607