Submission #849648

#TimeUsernameProblemLanguageResultExecution timeMemory
849648ntkphong철인 이종 경기 (APIO18_duathlon)C++14
66 / 100
120 ms25028 KiB
#include <bits/stdc++.h>
#define int long long
using namespace std;
 
const int mxN = 1e5 + 10;
 
vector<int> lab;
    
void init(int n) {
    lab.resize(n + 10);
    for(int i = 1; i <= n; i ++) lab[i] = -1;
}
    
int get_root(int u) {
    return lab[u] < 0 ? u : lab[u] = get_root(lab[u]);
}
    
bool unite(int u, int v) {
    u = get_root(u);
    v = get_root(v);
        
    if(u == v) return false;
    if(lab[u] > lab[v]) swap(u, v);
        
    lab[u] += lab[v];
    lab[v] = u;
        
    return true;
}
    
int get_size(int u) {
    u = get_root(u);
    return - lab[u];
}
 
int n, m;
vector<vector<int>> adj(mxN), vertex(mxN);
int num[mxN], low[mxN], timer = 0;
 
int vis[mxN];
long long dp[mxN][2];
long long sum = 0;
 
void tanjan(int u, int par) {
    num[u] = low[u] = ++ timer;
    
    for(int v : adj[u]) {
        if(v == par) continue ;
        
        if(num[v]) {
            low[u] = min(low[u], num[v]);
        } else {
            tanjan(v, u);
            low[u] = min(low[u], low[v]);
            
            if(low[v] <= num[u]) {
                unite(u, v);                
            }
        }
    }
}
 
void dfs(int u, int par) {
    int root = get_root(u);
    vis[root] = 1;
    
    sum += get_size(root) * (get_size(root) - 1) * (get_size(root) - 2);
    //cout << 3 << " " << get_size(root) * (get_size(root) - 1) * (get_size(root) - 2) << "\n";
    dp[root][0] = get_size(root);
    dp[root][1] = (get_size(root) - 1) * (get_size(root) - 1);
    
    for(int x : vertex[root]) {
        if(x == u) continue ;
        array<long long, 2> F = {0, 0};
            
        for(int v : adj[x]) {
            if(get_root(v) == root) continue ;
            if(vis[get_root(v)]) continue ;
            if(v == par) continue ;
                
            dfs(v, x);
                
            v = get_root(v);
            sum += 2LL * F[0] * dp[v][1] + 2LL * F[1] * dp[v][0] + 2LL * F[0] * dp[v][0];
            //cout << 1 << " " << 2LL * F[0] * dp[v][1] << " " << 2LL * F[1] * dp[v][0] + 2LL * F[0] * dp[v][0] << "\n";
            F[0] += dp[v][0];
            F[1] += dp[v][1]; 
        }
            
        sum += 2LL * dp[root][0] * F[1] + 2LL * dp[root][1] * F[0]; 
        //cout <<  2 << " " << 2LL * dp[root][0] * F[1] << " " << 2LL * dp[root][1] * F[0] << "\n";
        dp[root][0] += F[0];
        dp[root][1] += F[0] * get_size(root) + F[1];
    }
    
    for(int x : vertex[root]) {
        if(x != u) continue ;
        array<long long, 2> F = {0, 0};
            
        for(int v : adj[x]) {
            if(get_root(v) == root) continue ;
            if(vis[get_root(v)]) continue ;
            if(v == par) continue ;
                
            dfs(v, x);
                
            v = get_root(v);
            sum += 2LL * F[0] * dp[v][1] + 2LL * F[1] * dp[v][0] + 2LL * F[0] * dp[v][0];
            //cout << 1 << " " << 2LL * F[0] * dp[v][1] << " " << 2LL * F[1] * dp[v][0] + 2LL * F[0] * dp[v][0] << "\n";
            F[0] += dp[v][0];
            F[1] += dp[v][1]; 
        }
            
        sum += 2LL * dp[root][0] * F[1] + 2LL * dp[root][1] * F[0]; 
        //cout <<  2 << " " << 2LL * dp[root][0] * F[1] << " " << 2LL * dp[root][1] * F[0] << "\n";
        dp[root][0] += F[0];
        dp[root][1] += F[0] + F[1];
    }
}
 
signed main() {
 
    cin.tie(0)->sync_with_stdio(0);
 
    cin >> n >> m;
    
    init(n);
    
    for(int i = 1; i <= m; i ++) {
        int u, v;
        cin >> u >> v;
        
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    
    for(int i = 1; i <= n; i ++) if(!num[i]) tanjan(i, i);
    
    for(int i = 1; i <= n; i ++) {
        int root = get_root(i);
        vertex[root].push_back(i);
    } 
    
    for(int i = 1; i <= n; i ++) if(!vis[get_root(i)]) dfs(i, i); 
    
    cout << sum << "\n";
    return 0;
}
#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...