[洛谷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; }