제출 #1123626

#제출 시각아이디문제언어결과실행 시간메모리
1123626Denisov철인 이종 경기 (APIO18_duathlon)C++20
100 / 100
114 ms48236 KiB
//#pragma GCC optimize("Ofast", "unroll-loops")
//#pragma GCC target("sse", "sse2", "sse3", "ssse3", "sse4")

#include <bits/stdc++.h>

#define all(a) a.begin(),a.end()
#define len(a) (int)(a.size())
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
#define fi first
#define se second

using namespace std;

typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;

template<typename T>
bool umin(T &a, T b) {
    if (b < a) {
        a = b;
        return true;
    }
    return false;
}
template<typename T>
bool umax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

#ifdef KIVI
#define DEBUG for (bool _FLAG = true; _FLAG; _FLAG = false)
#define LOG(...) print(#__VA_ARGS__" ::", __VA_ARGS__) << endl
template <class ...Ts> auto &print(Ts ...ts) { return ((cerr << ts << " "), ...); }
#else
#define DEBUG while (false)
#define LOG(...)
#endif

const int max_n = (1e5 + 11) * 4, inf = 1000111222;

vector <int> edge[max_n];

int tin[max_n], tout[max_n], used[max_n], timer = 0, art[max_n], id[max_n], good[max_n];


vector <int> q, current;

vector <vector <int> > cmp;

inline void dfs (int v, int p = -1) {
    used[v] = 1;
    tin[v] = timer++;
    current.pb(v);
    tout[v] = tin[v];
    q.pb(v);
    for (int to : edge[v]) {
        if (to == p) {
            continue;
        }
        if (used[to]) {
            umin(tout[v], tin[to]);
        }
        else {
            dfs(to, v);
            umin(tout[v], tout[to]);
            if (tout[to] >= tin[v]) {
                art[v] = tin[v] > 0 || tin[to] > 1;
                cmp.pb(vector <int>{v});
                while (cmp.back().back() != to) {
                    cmp.back().pb(q.back());
                    q.pop_back();
                }
            }
        }
    }
}


vector <int> e[max_n];

int sz[max_n], n, save[max_n];



ll res[max_n];

ll ans = 0;

inline ll sqr (ll x) {
    return x * x;
}

inline void calc (int v, int p = -1) {
//    LOG(v, len(e[v]), sz[v], good[v]);
    ll cur = sz[v];
    save[v] = sz[v];
    for (int to : e[v]) {
        if (to == p) {
            continue;
        }
        calc(to, v);
        sz[v] += sz[to];
    }
    if (good[v]) {
        ans += cur * (cur - 1ll) * (len(current) - cur - len(e[v])) * 2ll; // 2 bad
//        LOG(cur * (cur - 1ll) * (len(current) - cur - len(e[v])) * 2ll);
//        if (p != -1) {
//            ans += cur * 2ll * (len(current) - sz[v] - 1);
//            LOG(cur * 2ll * (len(current) - sz[v] - 1));
//        }
//        for (int to : e[v]) {
//            if (to == p) {
//                continue;
//            }
//            ans += cur * 2ll * (sz[to] - 1ll);
//            LOG(cur * 2ll * (sz[to] - 1ll), "here");
//        }
        if (len(e[v]) >= 2) { // 2 good
            if (p != -1) {
                ans += (len(e[v]) - 1) * (len(e[v]) - 2ll) * 2ll * (len(current) - sz[v] - 1);
//                ans += (len(e[v]) - 1ll) * 2ll * (len(current) - sz[v] - 1);
            }
            for (int to : e[v]) {
                if (to == p) {
                    continue;
                }
                ans += (len(e[v]) - 1) * (len(e[v]) - 2ll) * 2ll * (sz[to] - 1ll);
//                ans += (len(e[v]) - 1ll) * 2ll * (sz[to] - 1ll);
            }
        }
        ll pref = 0; // 1 bad
        for (int to : e[v]) {
            ll now = sz[to] - 1;
            if (to == p) {
                now = len(current) - sz[v] - 1;
            }
            ans += cur * pref * now * 2ll;
//            LOG(cur * pref * now * 2);
            pref += now;
        }
        // 1 good
        pref = 0;
        for (int to : e[v]) {
            ll now = sz[to] - 1;
            if (to == p) {
                now = len(current) - sz[v] - 1;
            }
            ans += pref * now * len(e[v]) * 2ll;
            pref += now;
        }
    }
    else {
//        return;
        ll allow = len(current) - 1; // 1 bad 1 good
        for (int to : e[v]) {
            allow -= len(e[to]) - 1;
        }
        for (int to : e[v]) {
            ll now = save[to];
            allow -= now;
            ans += now * allow * 2ll;
        }
        // 1 good
//        ll pref = 0;
//        for (int to : e[v]) {
//            ll now = sz[to] - save[to] - len(e[to]) + 1;
//            if (to == p) {
//                now = len(current) - sz[v] - save[p] - len(e[p]) + 1;
//            }
//            ans += now * pref * 2ll;
//            pref += now;
//            LOG(now, pref);
//        }
    }
}


int val[max_n], V;

ll dp[max_n], cc[max_n];

inline void go (int v, int p = -1) {
    cc[v] = sz[v];
    dp[v] = 0;
    for (int to : e[v]) {
        if (to == p) {
            continue;
        }
        go(to, v);
        dp[v] += dp[to];
        cc[v] += cc[to];
    }
    dp[v] += cc[v] * (val[v] - 1ll);
}


inline void go_calc (int v, int p = -1, ll DP = 0, ll ccc = 0) {
    ll cur_dp = DP, cur_cc = ccc + sz[v];
    for (int to : e[v]) {
        if (to == p) {
            continue;
        }
        cur_dp += dp[to];
        cur_cc += cc[to];
    }
    ans += (cur_dp + (val[v] - 1ll) * (cur_cc - sz[v]) - (len(current) - sz[v])) * sz[v];
//    LOG(v, (cur_dp + (val[v] - 1ll) * (cc[v] - sz[v]) - (len(current) - sz[v])), DP, ccc);
//    cur_dp += (val[v] - 1ll) * cur_cc;
    for (int to : e[v]) {
        if (to == p) {
            continue;
        }
        ll now_dp = cur_dp - dp[to];
        ll now_cc = cur_cc - cc[to];
        now_dp += now_cc * (val[v] - 1ll);
        go_calc(to, v, now_dp, now_cc);
    }
}


int main() {
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int m;
    cin >> n >> m;
    for (int i = 0, a, b; i < m; i++) {
        a = i + 1, b = i + 2;
        cin >> a >> b;
        --a, --b;
        edge[a].pb(b);
        edge[b].pb(a);
    }
    int new_id = 0;
    for (int ver = 0; ver < n; ver++) {
        if (used[ver]) {
            continue;
        }
        timer = 0;
        current.clear();
        cmp.clear();
        q.clear();
        dfs(ver);
        if (len(current) == 1) {
            continue;
        }
        for (int i : current) {
            if (art[i]) {
                val[new_id] = 1;
                id[i] = new_id++;
                LOG(id[i], i);
            }
        }
        LOG(new_id);
        for (auto &i : cmp) {
            int now = new_id++, cnt = 0;
            good[now] = 1;
            val[now] = len(i);
            LOG(now, len(i));
            for (int x : i) {
                LOG(art[x], x);
                if (art[x]) {
                    e[id[x]].pb(now);
                    e[now].pb(id[x]);
//                    LOG(id[x], now);
                }
                else {
                    ++cnt;
                    id[x] = now;
                }
            }
//            ans += len(i) * (len(i) - 1ll) * (len(i) - 2ll);
//            for (int x : i) {
//                if (art[x]) {
//                    ans -= cnt * (cnt - 1ll) * 2;
//                }
//            }
//            ans += len(i) * (len(i) - 1ll) * (len(current) - len(i)) * 2ll;
//            LOG(len(i));
        }
//        LOG(new_id);
        for (int i : current) {
            ++sz[id[i]];
        }
        for (int i : current) {
            V = id[i];
//            go(id[i]);
            ans += (sz[V] - 1ll) * (val[V] - 2);
//            ans += (dp[V] - sz[V] * (val[V] - 1ll) - (len(current) - sz[V]));
//            LOG(V, (dp[V] - sz[V] * (val[V] - 1ll) - (len(current) - sz[V])));
            LOG(ans, i);
        }
        go(id[current[0]]);
        go_calc(id[current[0]]);
//        calc(id[ver]);
    }

    cout << ans << '\n';
}

/*
10 10
6 2
3 8
3 6
7 1
10 7
4 3
5 7
8 6
7 9
3 7

 10 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
 */
#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...