洛谷U643948 你爱我,我爱你 题解 强连通分量模板题
题目链接:https://www.luogu.com.cn/problem/U643948
题目大意:
给你一个有向图,求图中能够相互可达的节点对数。
解题思路:
同一个强连通分量内的任意两点之间相互可达。
所以,如果一个强连通分量的大小为 \(sz\),则其中相互可达的节点对数为 \(C_{sz}^2 = \frac{sz(sz-1)}{2}\)。
答案为 \(\sum \frac{sz(sz-1)}{2}\)。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, m, dfn[maxn], low[maxn], bl[maxn], ts, scc, sz[maxn];
bool ins[maxn];
stack<int> stk;
vector<int> g[maxn];
long long ans;
void tarjan(int u) {
dfn[u] = low[u] = ++ts;
stk.push(u);
ins[u] = true;
for (auto v : g[u]) {
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (ins[v])
low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
scc++;
int v;
do {
v = stk.top();
stk.pop();
ins[v] = false;
bl[v] = scc;
sz[scc]++;
} while (u != v);
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 0, u, v; i < m; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
tarjan(i);
for (int i = 1; i <= scc; i++) {
ans += 1ll * sz[i] * (sz[i] - 1) / 2;
}
printf("%lld\n", ans);
return 0;
}
浙公网安备 33010602011771号