Submission #1365994

#TimeUsernameProblemLanguageResultExecution timeMemory
1365994khanhphucscratchDuathlon (APIO18_duathlon)C++20
23 / 100
57 ms21532 KiB
#include<bits/stdc++.h>
#define int long long
using namespace std;
vector<int> ad[100005];
int low[100005], tin[100005], dfsc = 0;
bool visited[100005], joint[100005];
void dfs(int u, int par)
{
    visited[u] = 1; low[u] = tin[u] = ++dfsc;
    int child = 0;
    for(int v : ad[u]) if(v != par){
        if(visited[v] == 0){
            child++; dfs(v, u); low[u] = min(low[u], low[v]);
        }
        else low[u] = min(low[u], tin[v]);
    }
    if((par == -1 && child >= 2) || (par > -1 && child >= 1 && low[u] == tin[u])) joint[u] = 1;
}
vector<int> adtr[100005];
int color[100005], resz[100005], sz[100005], ans = 0;
bool marked[100005], joint_node[100005];
void dfs_sz(int u)
{
    marked[u] = 1; visited[u] = 1;
    for(int v : adtr[u]) if(visited[v] == 0){
        dfs_sz(v); sz[u] += sz[v];
    }
    visited[u] = 0;
}
void dfs_solve(int u)
{
    visited[u] = 1;
    //We're fixing the cc contain the middle
    //First case: all three node in the same cc
    int num = 0;
    for(int v : adtr[u]) if(joint_node[v] == 1) num++;
    ans += resz[u] * (resz[u] - 1) * num;
    //Second case: Two node in the same cc, and one node in another
    for(int v : adtr[u]){
        ans += resz[u] * (resz[u]-1) * sz[v] * 2;
    }
    //Last case: one node in this cc, two node in two branches
    int sum = 0;
    for(int v : adtr[u]){
        ans += sum * sz[v] * 2;
        sum += sz[v];
    }
    //Reroot
    for(int v : adtr[u]) if(visited[v] == 0){
        int rev = sz[v], reu = sz[u];
        sz[v] = sz[u] - sz[v]; swap(sz[u], sz[v]);
        dfs_solve(v);
        sz[u] = reu; sz[v] = rev;
    }
    visited[u] = 0;
}
signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m; cin>>n>>m;
    for(int i = 1; i <= m; i++){
        int u, v; cin>>u>>v;
        ad[u].push_back(v); ad[v].push_back(u);
    }
    for(int i = 1; i <= n; i++) if(visited[i] == 0) dfs(i, -1); //More than 1
    //Bfs
    int cc = 0;
    memset(visited, 0, sizeof(visited));
    for(int i = 1; i <= n; i++) if(visited[i] == 0){
        if(joint[i] == 1){
            color[i] = ++cc; sz[cc] = 1; visited[i] = joint_node[cc] = 1; continue;
        }
        queue<int> w; w.push(i); cc++; visited[i] = 1;
        while(w.size() > 0){
            int u = w.front(); w.pop(); color[u] = cc; sz[cc]++;
            for(int v : ad[u]) if(joint[v] == 0 && visited[v] == 0){
                visited[v] = 1; w.push(v);
            }
        }
    }
    for(int i = 1; i <= cc; i++) resz[i] = sz[i];
    //Compress
    vector<pair<int, int>> edges;
    for(int u = 1; u <= n; u++){
        for(int v : ad[u]) if(color[u] < color[v]){
            edges.push_back({color[u], color[v]});
        }
    }
    sort(edges.begin(), edges.end());
    edges.erase(unique(edges.begin(), edges.end()), edges.end());
    for(pair<int, int> i : edges){
        int u = i.first, v = i.second;
        adtr[u].push_back(v); adtr[v].push_back(u);
    }
    //Now solve
    memset(visited, 0, sizeof(visited));
    for(int i = 1; i <= cc; i++) if(marked[i] == 0){
        dfs_sz(i); dfs_solve(i);
    }
    cout<<ans;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...