Submission

Status:

(xSSSSSSSSS)(PPPPPPPPPPPP)(PPPPTSS)(PxSS)(PPxSSSS)(TSSSSSS)

Subtask/Task Score:

{0/4}{14/14}{0/12}{0/7}{0/20}{0/43}

Score: 14

User: Dormon

Problemset: อพยพปลอดภัย (Quartet)

Language: cpp

Time: 1.094 second

Submitted On: 2025-05-24 19:23:06

#include <iostream>
#include <vector>

using namespace std;
using ll = long long;
const ll mod = 1e9 + 7;

int n, m, k;
vector<ll> fac, inv;
vector<int> deg, dp;
vector<vector<int>> adj;

template<typename T> ostream &operator << (ostream &out, vector<T> v){
    out << "[";
    for (auto e:v) out << e << ' ';
    out << "]";
    return out;
}

ll bin_pow(ll b, ll n){
    ll res = 1ll;
    while (n > 0ll){
        if (n & 1ll)
            res = (res * b) % mod;
        b = (b * b) % mod;
        n >>= 1ll;
    }
    return res;
}

void init(int n, int m){
    fac.assign(n + 1, 1ll);
    inv.assign(n + 1, 1ll);
    adj.resize(n + m + 1);
    deg.assign(n + m + 1, 0);
    for (int i = 2;i <= n;i++) fac[i] = (fac[i - 1] * (i + 0ll)) % mod;
    inv[n] = bin_pow(fac[n], mod - 2);
    for (int i = n - 1;i >= 2;i--) inv[i] = (inv[i + 1] * (i + 1ll)) % mod;
}

ll nCr(int n, int r){
    if (n < r) return 0ll;
    return (((fac[n] * inv[r]) % mod) * inv[n - r]) % mod;
}

bool home(int u){
    return 1 <= u && u <= n;
}

void dfs(int u, int p){
    if (dp[u] != -1) return ;
    dp[u] = home(u);
    for (auto v:adj[u]){
        if (v == p) continue;
        dfs(v, u);
        dp[u] += dp[v];
    }
}

ll combi(vector<int> v, int h){
    int sz = v.size() - 1;
    vector<ll> pf(sz);
    for (int i = 1;i <= sz;i++)
        pf[i] = pf[i - 1] + v[i];
    ll res = 0ll;

    auto mul = [&](ll a, ll b) -> ll {
        return (a * b) % mod;
    };

    for (int i = 1;i <= sz;i++){
        for (int j = i + 1;j <= sz;j++){
            res += mul(h, mul(v[i], mul(v[j], pf[sz] - pf[j])));
            res %= mod;
        }
    }
    
    for (int i = 1;i <= sz;i++){
        res += mul(nCr(h, 2), mul(v[i], pf[sz] - pf[i]));
        res %= mod;
    }

    res += mul(nCr(h, 3), pf[sz]);
    res %= mod;
    res += nCr(h, 4);
    res %= mod;

    for (int i = 1;i <= sz;i++){
        for (int j = i + 1;j <= sz;j++){
            for (int l = j + 1;l <= sz;l++){
                res += mul(v[i], mul(v[j], mul(v[l], pf[sz] - pf[l])));
                res %= mod;
            }
        }
    }
    return res;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> m;
    k = n + m;
    init(n, m);

    for (int i = 1;i < k;i++){
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
        deg[u]++;
        deg[v]++;
    }

    bool can = false;

    for (int i = n + 1;i <= k;i++)
        if (deg[i] >= 4){
            can = true;
            break;
        }

    if (can == false){
        cout << "0\n";
        return 0;
    }

    ll ans = 0ll;

    for (int i = n + 1;i <= k;i++){
        if (deg[i] >= 4){
            dp.assign(k + 1, -1);
            dfs(i, -1);
            // cout << "dp " << i << " : " << dp << '\n';           
            int h = 0;
            vector<int> v = {0};
            for (auto next:adj[i]){
                if (dp[next] == 1) 
                    h++;
                else
                    v.push_back(dp[next]);
            }
            ans += combi(v, h);
            ans %= mod;
        }
    }
    cout << ans << '\n';
}