Codeforces Round #686 (Div. 3)

Codeforces Round #686 (Div. 3)

E. Number of Simple Paths

思路:因为这个图的边和点的数量相等,所以保证图上只有一个简单环,我们找到这个环,把这个环上所有的边断掉,然后将这个环上所有点连向一个虚拟点 (0) ,以 (0) 为根(写的时候不用这么麻烦,这么说只是为了便于理解),统计父节点是 (0) 的所有子树的 (sz_1, sz_2, sz_3 .... sz_k) ,那么答案就是 ((sum_{i = 1}^k sum_{j = i + 1}^k sz_i * sz_j + n * (n - 1) / 2))

我是用 (dfs) 树实现的,下面是代码

#include <bits/stdc++.h>
using namespace std;
#define lc (rt << 1)
#define rc ((rt << 1) | 1)
#define fi first
#define se second
#define pb push_back
#define pii pair<int, int>
#define rep(i, l, r) for (int i = (l); i <= (r); ++i)
#define per(i, r, l) for (int i = (r); i >= (l); --i)
#define PE(i, u) for (int i = head[u]; i != -1; i = edge[i].next)
typedef long long LL;
const int maxn = 1e6 + 20;
const int mod = 1e9 + 7;
int n, m;
struct Edge
{
    int to, next;
} edge[maxn * 2];
int k, head[maxn];
void add(int a, int b){
    edge[k].to = b;
    edge[k].next = head[a];
    head[a] = k++;
}
int d[maxn], dp[maxn], sz[maxn];
LL ans = 0;
int sum;
void dfs(int u, int fa){
    sz[u] = 1;
    PE(i, u){
        int to = edge[i].to;
        if(to == fa) continue;
        if(!d[to]) {
            d[to] = d[u] + 1;
            dfs(to, u);
            dp[u] += dp[to];
            sz[u] += sz[to];
        } else if(d[to] > d[u]) dp[u]--;
        else if(d[to] < d[u]) {
            dp[u]++;
        }
    }
    if(dp[u]) {
        ans += 1LL * (sum - sz[u]) * sz[u];
        sum -= sz[u];
        sz[u] = 0;
    }
}

int main(int argc, char const *argv[])
{
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        sum = n;
        ans = 0;
        ans = 1LL * n * (n - 1) / 2;
        rep(i, 1, n){
            dp[i] = sz[i] = d[i] = 0;
            head[i] = -1;
        }
        rep(i, 1, n){
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v), add(v, u);
        }
        d[1] = 1;
        dfs(1, 0);
        printf("%lld
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/PCCCCC/p/14037857.html