Submission #1118851

#TimeUsernameProblemLanguageResultExecution timeMemory
1118851OI_AccountDuathlon (APIO18_duathlon)C++17
100 / 100
190 ms43036 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N = 300'000;

int n, m;
int tim, st[N + 10], ft[N + 10];
int mark[N + 10], h[N + 10], mnH[N + 10];
int s, type[N + 10], sz[N + 10];
vector<int> adj[N + 10], g[N + 10], vec;
vector<vector<int>> block;
ll ans, tmpN;

void readInput() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
}

void check(int u, int v) {
    if (mnH[v] < h[u])
        return;
    vector<int> good = {u};
    while (vec.size()) {
        int w = vec.back();
        if (st[v] <= st[w] && ft[w] <= ft[v]) {
            good.push_back(w);
            vec.pop_back();
        }
        else
            break;
    }
    block.push_back(good);
}

void dfs(int u, int par = 0) {
    mark[u] = 1;
    st[u] = ++tim;
    h[u] = mnH[u] = h[par] + 1;
    for (auto v: adj[u])
        if (!mark[v]) {
            dfs(v, u);
            check(u, v);
            mnH[u] = min(mnH[u], mnH[v]);
        }
        else
            mnH[u] = min(mnH[u], h[v]);
    vec.push_back(u);
    ft[u] = tim;
}

void calcBlock() {
    for (int i = 1; i <= n; i++)
        if (!mark[i])
            dfs(i);
}

void addEdge(int u, int v) {
    g[u].push_back(v);
    g[v].push_back(u);
}

void calcG() {
    s = n;
    fill(type + 1, type + n + 1, 1);
    fill(mark + 1, mark + n + 1, 0);
    for (int i = 0; i < block.size(); i++) {
        s++;
        type[s] = 2;
        //cout << "block " << i << ": ";
        for (auto u: block[i])
            addEdge(u, s);
            //cout << u << ' ';
        //cout << endl;
    }
}

void dfsSz(int u, int par = 0) {
    sz[u] = (type[u] == 1);
    mark[u] = true;
    for (auto v: g[u])
        if (v != par) {
            dfsSz(v, u);
            sz[u] += sz[v];
        }
}

void addAns(int u, int par) {
    ll mul = 0, sum = tmpN - sz[u];
    for (auto v: g[u])
        if (v != par) {
            mul += sum * sz[v];
            sum += sz[v];
        }
    ans += mul * (ll) block[u - n - 1].size() * 2;
}

void delAns(int u, int par) {
    ll mul = 0, sum = tmpN - sz[u];
    for (auto v: g[u])
        if (v != par) {
            mul += sum * sz[v];
            sum += sz[v];
        }
    ans -= mul * 2ll;
}

void dfsAns(int u, int par = 0) {
    if (type[u] == 2)
        addAns(u, par);
    else
        delAns(u, par);
    for (auto v: g[u])
        if (v != par)
            dfsAns(v, u);
}

void checkCmp(int u) {
    dfsSz(u);
    tmpN = sz[u];
    dfsAns(u);
    ans -= tmpN * (tmpN - 1) * 2;
}

void calcAns() {
    for (int i = 1; i <= n; i++)
        if (!mark[i])
            checkCmp(i);
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    readInput();
    calcBlock();
    calcG();
    calcAns();
    cout << ans << flush;
    return 0;
}

/*
4 3
1 2
2 3
3 4
*/

/*
4 4
1 2
2 3
3 4
4 2
*/

Compilation message (stderr)

count_triplets.cpp: In function 'void calcG()':
count_triplets.cpp:73:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   73 |     for (int i = 0; i < block.size(); i++) {
      |                     ~~^~~~~~~~~~~~~~
#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...