bzoj1123 [POI2008]BLO
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1123
【题解】
tarjan算割点的时候顺便统计即可。
割点的条件是
low[to[i]]>=dfn[x],说明删掉点x这一段就不和其他联通了。
先算不包含祖先的其他连通块的贡献,最后加包含祖先的贡献即可。
这题输出方式奇怪啊。。具体见本题discuss
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 1e6 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, m; int head[M], nxt[M], to[M], tot=0; inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } inline void adde(int u, int v) { add(u, v), add(v, u); } int dfn[M], low[M], sz[M], DFN=0; ll ans[M]; inline void tarjan(int x, int fa=0) { ll t=0; dfn[x] = low[x] = ++DFN; sz[x] = 1; for (int i=head[x]; i; i=nxt[i]) { if(to[i] == fa) continue; if(!dfn[to[i]]) { tarjan(to[i], x); sz[x] += sz[to[i]]; low[x] = min(low[x], low[to[i]]); if(low[to[i]] >= dfn[x]) { ans[x] += t*sz[to[i]]; t += sz[to[i]]; } } else low[x] = min(low[x], dfn[to[i]]); } ans[x] += t*(n-t-1); } int main() { cin >> n >> m; for (int i=1, u, v; i<=m; ++i) { scanf("%d%d", &u, &v); adde(u, v); } tarjan(1); // for (int i=1; i<=n; ++i) printf("%d %d\n", dfn[i], low[i]); for (int i=1; i<=n; ++i) ans[i] = (ans[i] + n-1)*2; for (int i=1; i<=n; ++i) printf("%lld\n", ans[i]); return 0; }