题目链接:简单路径

分析:

可以考虑余事象

若图上所有点都在环上,由于环上任意两点可确定两条简单路径,于是答案就是 \(\binom{n}{2} \times 2 = n(n-1)\)

再考虑环上的点会引出子树的情况,对于子树上的任意两点可以确定 \(\binom{t_i}{2}\) 条简单路径,其中 \(t_i\) 表示该子树的大小

利用余事象,得到最后的答案为 \(n(n-1) - \sum \binom{t_i}{2}\)

注意:由于本题统计的是有向路径,所以要对答案乘以 \(2\)

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;

//const int mod = 998244353;
const int mod = 1000000007;
struct mint {
    ll x;
    mint(ll x=0):x((x%mod+mod)%mod) {}
    mint operator-() const {
        return mint(-x);
    }
    mint& operator+=(const mint a) {
        if ((x += a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator-=(const mint a) {
        if ((x += mod-a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator*=(const mint a) {
        (x *= a.x) %= mod;
        return *this;
    }
    mint operator+(const mint a) const {
        return mint(*this) += a;
    }
    mint operator-(const mint a) const {
        return mint(*this) -= a;
    }
    mint operator*(const mint a) const {
        return mint(*this) *= a;
    }
    mint pow(ll t) const {
        if (!t) return 1;
        mint a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }

    // for prime mod
    mint inv() const {
        return pow(mod-2);
    }
    mint& operator/=(const mint a) {
        return *this *= a.inv();
    }
    mint operator/(const mint a) const {
        return mint(*this) /= a;
    }
};
istream& operator>>(istream& is, mint& a) {
    return is >> a.x;
}
ostream& operator<<(ostream& os, const mint& a) {
    return os << a.x;
}

int main() {
    int n;
    cin >> n;
    
    vector<vector<int>> to(n);
    vector<int> deg(n);
    rep(i, n) {
        int a, b;
        cin >> a >> b;
        --a; --b;
        to[a].push_back(b);
        to[b].push_back(a);
        deg[a]++;
        deg[b]++;
    }
    
    vector<int> t(n, 1);
    queue<int> q;
    rep(i, n) if (deg[i] == 1) q.push(i);
    while (q.size()) {
        int v = q.front(); q.pop();
        for (int u : to[v]) {
            deg[u]--;
            if (deg[u] == 1) q.push(u);
            t[u] += t[v];
        }
    }
    
    mint ans = mint(n)*(n-1);
    rep(i, n) {
        if (deg[i] == 2) {
            mint now = t[i];
            now *= t[i]-1;
            now /= 2;
            ans -= now;
        }
    }
    ans *= 2;
    
    cout << ans << '\n';
    
    return 0;
}