#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |