// 题意:对于每一个点,求删去这个点的所有边会形成多少个点对满足两点之间不互通 // 思路:思路很简单,分为这个点是否是割点,但写法上就有点讲究,详情见博客 // /*#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int n, m; vector<int> e[N]; int dfn[N], low[N], idx, cut[N], ans[N], id, sz[N]; void dfs(int u, int f) { dfn[u] = low[u] = ++idx; int ch = 0; sz[id]++; for (auto v : e[u]) { if (!dfn[v]) { dfs(v, u); ch++; low[u] = min(low[u], low[v]); if (low[v] >= dfn[u]) { ans[u] = 2 * (n - sz[id]) * sz[id] + 2 * (n - sz[id] - 1); cut[u] = 1; ++id; } } else if (v != f) { low[u] = min(low[u], dfn[v]); sz[id]++; } } if (u == 1 && ch <= 1) cut[u] = 0; if (cut[u] == 0)ans[u] = 2 * (n - 1); } int main() { cin >> n >> m; id = 1; for (int i = 1; i <= m; i++) { int a, b; cin >> a >> b; e[a].push_back(b); e[b].push_back(a); } dfs(1, -1); for (int i = 1; i <= n; i++) cout << ans[i] << endl; return 0; }*/ #include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int n, m; vector<int> e[N]; int dfn[N], low[N], idx, sz[N]; long long ans[N]; void dfs(int u, int f) { dfn[u] = low[u] = ++idx; sz[u] = 1; ans[u] = n - 1; int cut = n - 1; for (auto v : e[u]) { if (!dfn[v]) { dfs(v, u); sz[u] += sz[v]; low[u] = min(low[u], low[v]); if (low[v] >= dfn[u]) { ans[u] += (long long)sz[v] * (n - sz[v]); cut -= sz[v]; } } else if (v != f) { low[u] = min(low[u], dfn[v]); } } ans[u] += (long long)cut * (n - cut); } int main() { cin >> n >> m; for (int i = 1; i <= m; i++) { int a, b; cin >> a >> b; e[a].push_back(b); e[b].push_back(a); } dfs(1, -1); for (int i = 1; i <= n; i++) cout << ans[i] << endl; return 0; }
标签:sz,POI2008,int,割点,dfs,Blockade,dfn,low,id From: https://www.cnblogs.com/Aacaod/p/17040962.html