제출 #1271356

#제출 시각아이디문제언어결과실행 시간메모리
1271356SpyrosAliv철인 이종 경기 (APIO18_duathlon)C++20
23 / 100
740 ms1114112 KiB
#include <bits/stdc++.h>
using namespace std;
#define int long long

// make articulation tree
// w_u * (w_u - 1) * (w_u - 2) + w_u * (w_u - 1) * (n - w_u) * 2

const int MN = 1e5+5;
vector<vector<int>> g(MN);
vector<vector<int>> tree(MN);
int n, m, ans = 0;
vector<bool> art(MN, false), vis(MN, false);
vector<int> low(MN, 0), dep(MN, 0), below(MN, 0);
int t = 0, tot = 0;
int par[MN], sz[MN];

int find(int u) {
    if (par[u] == u) return u;
    return par[u] = find(par[u]);
}

void merge(int u, int v) {
    u = find(u);
    v = find(v);
    if (u == v) return;
    if (sz[u] > sz[v]) swap(u, v);
    par[u] = v;
    sz[v] += sz[u];
}

void dfs(int node, int p = 0) {
    vis[node] = true;
    dep[node] = dep[p] + 1;
    low[node] = dep[node];
    for (auto next: g[node]) {
        if (next == p) continue;
        if (vis[next]) {
            low[node] = min(low[node], dep[next]);
            continue;
        }
        dfs(next, node);
        below[node] += below[next];
        low[node] = min(low[node], low[next]);
        if (low[next] >= dep[node]) art[node] = true;
    }
    if (g[node].size() == 1) art[node] = true;
}

void get_below(int node, int par = 0) {
    below[node] = sz[node];
    for (auto next: tree[node]) {
        if (next == par) continue;
        get_below(next, node);
        below[node] += below[next];
    }
}

void dfs2(int node, int par, int tot) {
    vis[node] = true;
    vector<int> subs;
    int ss = 0;
    for (auto next: tree[node]) {
        if (next == par) continue;
        subs.push_back(below[next]);
        ss += below[next];
    }
    subs.push_back(tot - below[node]);
    ss += subs.back();
    for (auto v: subs) {
        ans += v * (ss - v);
    }
    for (auto next: tree[node]) {
        if (next == par) continue;
        dfs2(next, node, tot);
    }
}

void get_ans(int root) {
    get_below(root);
    tot = below[root];
    dfs2(root, 0, tot);
}

signed main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    for (int i = 1; i <= n; i++) {
        if (!vis[i]) {
            dfs(i);
        }
    }
    for (int i = 1; i <= n; i++) {
        sz[i] = 1;
        par[i] = i;
    }
    for (int i = 1; i <= n; i++) {
        if (art[i]) continue;
        for (auto next: g[i]) {
            if (art[next]) continue;
            merge(i, next);
        }
    }
    for (int i = 1; i <= n; i++) {
        if (find(i) != i || art[i]) continue;
        ans += sz[i] * (sz[i] - 1) * (sz[i] - 2) + 2 * sz[i] * (sz[i] - 1) * (n - sz[i]); 
    }
    for (int i = 1; i <= n; i++) {
        if (!art[i]) continue;
        set<int> conn;
        for (auto next: g[i]) {
            if (art[next] && next < i) continue;
            conn.insert(find(next));
        }
        for (auto v: conn) {
            tree[i].push_back(v);
            tree[v].push_back(i);
        }
    }
    vis.assign(n+1, false);
    for (int i = 1; i <= n; i++) {
        if (vis[i] || find(i) != i) continue;
        get_ans(find(i));
    }
    cout << ans << "\n";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...