L3-032深さ優先探索と逆順序対についての質問は難しいことではありませんよね?

ポータル
のアイデア:
「私は小さなカタツムリです」
namoからの参照は、リメイクを除いて、2人の教師と同じくらい強いことができ
ますか?親子関係を持つポイントペアが逆になっているかどうか、別のdfsシーケンスを検討してください。親子関係はありません。ポイントペアが逆になっているかどうかの確率は、それぞれ1 2 \ frac{1}{2}を占めています。21
dfsの序数を数え、サブツリーのdfsの序数を維持することを検討してください。現在のノードのdfsの序数は(∏ \ prod子ノードをルートとするサブツリーのdfs序数)×\ times×(子ノードの順列の数)
コード:
f []は、サブツリーとしてuを使用するdfs順序付けスキームの数、cntRevは、dfs順序で決定された逆順序ペアの数、cntNumは、決定された逆順序ペアの数です。 dfsオーダー番号では、numは親子関係のないポイントペアの数です。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll mod = 1e9 + 7;
const ll N = 3e5 + 10;

vector<ll> g[N];
ll tree[N];
ll n, rt;

ll qpow(ll x, ll n) {
    
    
    ll res = 1;
    while (n) {
    
    
        if (n & 1) res = res * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return res;
}

ll lowbit(ll x) {
    
    
    return x & (-x);
}

void add(ll p, ll x) {
    
    
    while (p <= n) {
    
    
        tree[p] = (tree[p] + x) % mod;
        p += lowbit(p);
    }
}

ll query(ll p) {
    
    
    ll res = 0;
    while (p) {
    
    
        res = (res + tree[p]) % mod;
        p -= lowbit(p);
    }
    return res;
}

ll cntRev = 0, cntNum = 0;
ll f[N];
ll fac[N];

void dfs(ll x, ll p) {
    
    
    f[x] = 1;
    for (auto to : g[x]) {
    
    
        if (to == p) continue;
        cntRev = (cntRev + query(n) - query(to) + mod) % mod;
        cntNum = (cntNum + query(to)) % mod;
        add(to, 1);
        dfs(to, x);
        f[x] = f[x] * f[to] % mod;
        add(to, -1);
    }
    ll num = (x == rt ? g[x].size() : g[x].size() - 1);
    f[x] = f[x] * fac[num] % mod;
}


signed main() {
    
    
    ios::sync_with_stdio(false), cin.tie(nullptr);

    fac[0] = 1;
    for (ll i = 1; i < N; ++i) fac[i] = fac[i - 1] * i % mod;

    cin >> n >> rt;
    for (ll i = 1; i <= n - 1; ++i) {
    
    
        ll x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }

    add(rt, 1);
    dfs(rt, -1);

    ll num = ((n * (n - 1) % mod * qpow(2, mod - 2) % mod - cntRev - cntNum) % mod + mod) % mod;
    ll ans = f[rt] * (cntRev + num * qpow(2, mod - 2) % mod) % mod;
    cout << ans << endl;
}

おすすめ

転載: blog.csdn.net/qq_39602052/article/details/124461408
おすすめ