zoukankan      html  css  js  c++  java
  • 【atc abc160F】F

    传送门

    题意:
    求以每个点为根节点的树的拓扑序计数。

    思路:
    是一个挺经典的问题。
    我们考虑自下而上的树形(dp):假设我们当前点在(u),我们已经求出来了(dp[v],vin sons_u)
    现在要求(u)的方案数,我们考虑在(u)放上(1),然后剩下(sz[u]-1)个数生成一个排列依次给每个结点赋值。之后类似于一个可重集的排列问题,对于每个结点,我们要除以(sz[v]!),就相当于我们从(sz[u]-1)个数中拿出来一些数给(v)这颗子树赋值,不考虑顺序的情况下,这些数不同的方案数。接下来就考虑上顺序,乘以一个(dp[v])就行。所以总的方案数为:

    [(sz[u] - 1)!cdot prodfrac{dp[i]}{sz[i]!},uin father(i) ]

    当然,还有更加简单的公式,我们不用考虑(dp),因为我们发现首位固定最小的排列数为((n-1)!)。那么对于以(u)为根节点的子树答案为:

    [sz[u]!prodfrac{1}{sz[i]},uin father(i) ]

    这两个式子是等价的,我们可以直接归纳证明。

    这样就求出来了以一个点作为根节点的情况,求所有点作为根结点的情况直接换根跑一下就行。
    细节见代码:

    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/16 17:42:54
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e5 + 5, MOD = 1e9 + 7;
    
    int qpow(ll a, ll b) {
        ll res = 1;
        while (b) {
            if (b & 1) res = res * a % MOD;
            a = a * a % MOD;
            b >>= 1;   
        }
        return res;   
    }
    
    int n;
    vector <int> G[N];
    int sz[N], f[N];
    
    void dfs(int u, int fa) {
        sz[u] = 1;
        for (auto v : G[u]) if (v != fa) {
            dfs(v, u);
            sz[u] += sz[v];
        }
    }
    
    void dfs2(int u, int fa) {
        for (auto v : G[u]) if (v != fa) {
            f[v] = 1ll * f[u] * sz[v] % MOD * qpow(n - sz[v], MOD - 2) % MOD;
            dfs2(v, u);
        }
    }
    
    void run() {
        cin >> n;
        for (int i = 1; i < n; i++) {
            int u, v; cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1, 0);
        f[1] = 1;
        for (int i = 1; i <= n; i++) {
            f[1] = 1ll * f[1] * i % MOD;
        }
        for (int i = 1; i <= n; i++) {
            f[1] = 1ll * f[1] * qpow(sz[i], MOD - 2) % MOD;
        }
        dfs2(1, 0);
        for (int i = 1; i <= n; i++) {
            cout << f[i] << '
    ';   
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
    
  • 相关阅读:
    ACL的基本访问列表与高级访问列表
    ACL配置
    OSPF与ACL综合应用
    RSTP基础配置
    基于接口地址池和基于全局配置的DHCP
    在ensp上通过FTP进行文件操作
    在ensp上配置通过Stelnet登录系统
    在ensp上配置通过Telent登录系统
    在eNSP上简单的模拟企业网络场景(不同网段互连)
    虚拟机中使用Samba实现文件共享
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/12912044.html
Copyright © 2011-2022 走看看