zoukankan      html  css  js  c++  java
  • 换根DP(二次扫描)

    参考来自这里:

    https://blog.csdn.net/qq_41286356/article/details/94554729

    题目在这里

    https://ac.nowcoder.com/acm/contest/375/C

    这题真的好,算是排列组合+树形DP的结合 吧

    这题换个问法就是 :   给树节点标号,使得所有节点的父节点都比子节点大,这样的编号方法有几种?

    第一次扫描,计算一个根:

     第二次扫描,推进算出所有根

    妙啊!

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cstdio>
    #define maxn 100010
    using namespace std;
    typedef long long ll;
    const ll mod = 998244353;
    vector<int>G[maxn];
    void insert(int be, int en) {
        G[be].push_back(en);
    }
    
    ll inv(ll a) {
        ll n = mod - 2;
        ll res = 1;
        while (n) {
            if (n & 1) {
                res = (res*a) % mod;
            }
            n >>= 1;
            a = (a*a) % mod;
        }
        return res;
    }
    
    ll dp[maxn];
    ll in[maxn];
    ll C(int n, int m) {
        ll ans = (in[n] * inv(in[m])) % mod;
        ans = (ans * inv(in[n - m])) % mod;
        return ans;
    }
    
    
    ll son[maxn];
    int n;
    
    int dfs(int x,int fa) {
        dp[x] = son[x] = 1;
    
        for (int i = 0; i < G[x].size(); i++) {
            int p = G[x][i];
            if (p == fa) continue;
            dfs(p, x);
            son[x] += son[p];
        }
        ll cnt = 0;
        for (int i = 0; i < G[x].size(); i++) {
            int p = G[x][i];
            if (p == fa) continue;
            ll a = son[x] - 1 - cnt;
            ll b = son[p];
            dp[x] = (((dp[x] * C(a, b)) % mod)*dp[p]) % mod;
            cnt += son[p];
        }
        return 0;
    }
    
    
    int dfs1(int x, int fa) {
        for(int i = 0; i < G[x].size(); i++) {
            int p = G[x][i];
            if (p == fa) continue;
            ll tmp = ((dp[x] * inv(dp[p])) % mod)*inv(C(n - 1, son[p])) % mod;
            dp[p] = (((dp[p] * C(n - 1, n - son[p])) % mod)*tmp )% mod;
            dfs1(p, x);
        }
        return 0;
    }
    
    int main() {
        
        int be, en;
        in[0] = 1;
        for (int i = 1; i <= 1e5+4; i++) {
            in[i] = (in[i - 1] * i) % mod;
        }
    
        scanf("%d", &n);
        
        for (int i = 1; i < n; i++) {
            scanf("%d%d", &be, &en);
            insert(be, en);
            insert(en, be);
        }
        dfs(1, -1);
        dfs1(1, -1);
        ll ans = 0;
        for (int i = 1; i <= n; i++) {
            ans = (ans + dp[i]) % mod;
        }
        printf("%lld
    ", ans);
        return 0;
    }
    寻找真正的热爱
  • 相关阅读:
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    Codeforces Round #601 (Div. 2) E2 Send Boxes to Alice (Hard Version)
    Codeforces Round #601 (Div. 2) E1 Send Boxes to Alice (Easy Version)
  • 原文地址:https://www.cnblogs.com/lesning/p/12049331.html
Copyright © 2011-2022 走看看