제출 #1213345

#제출 시각아이디문제언어결과실행 시간메모리
1213345spike1236철인 이종 경기 (APIO18_duathlon)C++20
0 / 100
98 ms45872 KiB
#include <bits/stdc++.h>
using namespace std;

int n, m;
vector<vector<int>> adj;
vector<int> disc, low;
vector<bool> is_art;
int time_dfs;
vector<pair<int,int>> edgeStack;
vector<vector<int>> bcc_list;
vector<vector<int>> vertex_to_bcc;
vector<int> in_comp;

void tarjan(int u, int parent) {
    disc[u] = low[u] = ++time_dfs;
    int child_count = 0;
    for (int v : adj[u]) {
        if (disc[v] == 0) {
            child_count++;
            edgeStack.emplace_back(u, v);
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (parent != -1 && low[v] >= disc[u]) is_art[u] = true;
            if (parent == -1 && child_count > 1) is_art[u] = true;
            if (low[v] >= disc[u]) {
                int id = bcc_list.size();
                vector<int> comp;
                while (true) {
                    auto e = edgeStack.back();
                    edgeStack.pop_back();
                    int x = e.first, y = e.second;
                    if (in_comp[x] != id + 1) {
                        in_comp[x] = id + 1;
                        comp.push_back(x);
                    }
                    if (in_comp[y] != id + 1) {
                        in_comp[y] = id + 1;
                        comp.push_back(y);
                    }
                    if ((x == u && y == v) || (x == v && y == u)) break;
                }
                bcc_list.push_back(comp);
                for (int w : comp) vertex_to_bcc[w].push_back(id);
            }
        } else if (v != parent && disc[v] < disc[u]) {
            low[u] = min(low[u], disc[v]);
            edgeStack.emplace_back(u, v);
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

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

    disc.assign(n + 1, 0);
    low.assign(n + 1, 0);
    is_art.assign(n + 1, false);
    time_dfs = 0;
    vertex_to_bcc.assign(n + 1, {});
    in_comp.assign(n + 1, 0);

    for (int i = 1; i <= n; i++) {
        if (disc[i] == 0) {
            tarjan(i, -1);
            if (!edgeStack.empty()) {
                int id = bcc_list.size();
                vector<int> comp;
                while (!edgeStack.empty()) {
                    auto e = edgeStack.back();
                    edgeStack.pop_back();
                    int x = e.first, y = e.second;
                    if (in_comp[x] != id + 1) {
                        in_comp[x] = id + 1;
                        comp.push_back(x);
                    }
                    if (in_comp[y] != id + 1) {
                        in_comp[y] = id + 1;
                        comp.push_back(y);
                    }
                }
                bcc_list.push_back(comp);
                for (int w : comp) vertex_to_bcc[w].push_back(id);
            }
        }
    }

    int num_bcc = bcc_list.size();
    int totalNodes = n + num_bcc;
    vector<vector<int>> bct_adj(totalNodes + 1);
    vector<long long> weight(totalNodes + 1, 0);
    vector<int> B_sz(num_bcc);

    for (int bcc_id = 0; bcc_id < num_bcc; bcc_id++) {
        B_sz[bcc_id] = bcc_list[bcc_id].size();
    }

    for (int v = 1; v <= n; v++) {
        if (is_art[v]) weight[v] = 1;
    }

    for (int bcc_id = 0; bcc_id < num_bcc; bcc_id++) {
        int node_id = n + 1 + bcc_id;
        int art_count = 0;
        for (int v : bcc_list[bcc_id]) {
            if (is_art[v]) {
                art_count++;
                bct_adj[node_id].push_back(v);
                bct_adj[v].push_back(node_id);
            }
        }
        weight[node_id] = B_sz[bcc_id] - art_count;
    }

    vector<int> parent(totalNodes + 1, -1);
    vector<bool> visited_bct(totalNodes + 1, false);
    vector<long long> size_subtree(totalNodes + 1, 0);
    vector<long long> comp_total(totalNodes + 1, 0);

    for (int start = 1; start <= totalNodes; start++) {
        if (start <= n && !is_art[start]) continue;
        if (visited_bct[start]) continue;
        vector<int> comp_nodes;
        stack<pair<int,int>> stk;
        parent[start] = 0;
        visited_bct[start] = true;
        comp_nodes.push_back(start);
        stk.push({start, 0});
        while (!stk.empty()) {
            int node = stk.top().first;
            int &idx = stk.top().second;
            if (idx < (int)bct_adj[node].size()) {
                int nei = bct_adj[node][idx];
                idx++;
                if (!visited_bct[nei]) {
                    visited_bct[nei] = true;
                    parent[nei] = node;
                    comp_nodes.push_back(nei);
                    stk.push({nei, 0});
                }
            } else {
                long long total_w = weight[node];
                for (int w : bct_adj[node]) {
                    if (parent[w] == node) total_w += size_subtree[w];
                }
                size_subtree[node] = total_w;
                stk.pop();
            }
        }
        long long totW = size_subtree[start];
        for (int u : comp_nodes) comp_total[u] = totW;
    }

    long long answer = 0;
    for (int c = 1; c <= n; c++) {
        if (!is_art[c]) {
            int bcc_id = vertex_to_bcc[c][0];
            int bnode = n + 1 + bcc_id;
            long long D0 = (long long)B_sz[bcc_id] - 1;
            long long L0 = 0, sum_l2 = 0;
            for (int a : bct_adj[bnode]) {
                long long comp_ab;
                if (parent[a] == bnode) {
                    comp_ab = size_subtree[a];
                } else {
                    comp_ab = comp_total[bnode] - size_subtree[bnode];
                }
                long long li = comp_ab - 1;
                L0 += li;
                sum_l2 += li * li;
            }
            long long term = 0;
            if (D0 >= 2) term += D0 * (D0 - 1);
            term += (L0 * L0 - sum_l2);
            term += 2LL * (D0 - 1) * L0;
            answer += term;
        } else {
            long long sum_S = 0, sum_S_sq = 0;
            long long sum_intra = 0;
            for (int bnode : bct_adj[c]) {
                long long S_j;
                if (parent[bnode] == c) {
                    S_j = size_subtree[bnode];
                } else {
                    S_j = comp_total[c] - size_subtree[c];
                }
                sum_S += S_j;
                sum_S_sq += S_j * S_j;
                int bcc_id = bnode - n - 1;
                long long D_j = (long long)B_sz[bcc_id] - 1;
                long long L_j = 0, sum_l2 = 0;
                for (int a : bct_adj[bnode]) {
                    if (a == c) continue;
                    long long comp_ab;
                    if (parent[a] == bnode) {
                        comp_ab = size_subtree[a];
                    } else {
                        comp_ab = comp_total[bnode] - size_subtree[bnode];
                    }
                    long long l_i = comp_ab - 1;
                    L_j += l_i;
                    sum_l2 += l_i * l_i;
                }
                long long intra = 0;
                if (D_j >= 2) intra += D_j * (D_j - 1);
                intra += (L_j * L_j - sum_l2);
                intra += 2LL * (D_j - 1) * L_j;
                sum_intra += intra;
            }
            long long cross_pairs = sum_S * sum_S - sum_S_sq;
            answer += cross_pairs + sum_intra;
        }
    }

    cout << answer << "\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...