[洛谷P3469][POI2008]BLO-Blockade
题目大意:给你一张无向图,求出删去每个点后有多少个有序点对无法互相到达
题解:缩点,然后找割点$DP$,非割点的答案为$2n-2$(有序点对),割点的答案为它各个子联通块大小之积加上$2n-2$
卡点:无
C++ Code:
#include <cstdio>
#define maxn 100010
#define maxm 500010
int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxm << 1];
inline void add(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
}
inline int min(int a, int b) {return a < b ? a : b;}
int n, m;
int DFN[maxn], low[maxn], idx;
int sz[maxn];
long long ans[maxn];
void tarjan(int u, int fa = 0) {
DFN[u] = low[u] = ++idx;
int SZ = 0;
sz[u] = 1;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa) {
if (!DFN[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] >= DFN[u]) {
ans[u] += static_cast<long long> (sz[v]) * SZ;
SZ += sz[v];
}
sz[u] += sz[v];
} else low[u] = min(low[u], DFN[v]);
}
}
ans[u] += static_cast<long long> (n - SZ - 1) * SZ;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 0, a, b; i < m; i++) {
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
}
tarjan(1);
for (int i = 1; i <= n; i++) {
printf("%lld\n", ans[i] + n - 1 << 1);
}
return 0;
}

浙公网安备 33010602011771号