初学tarjan求调
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
vector<int> child[maxn];
int dfn[maxn];
int dfsclock;
bool iscut[maxn];
vector<int> scc[maxn];
int cnt;
bool vis[maxn];
int c[maxn];
int siz[maxn];
int s[maxn];
set<int> to[maxn];
set<int> con;
vector<int> buff;
int tarjan(int pa, int p) {
int lowp = dfn[p] = ++dfsclock;
int chi = 0;
buff.push_back(p);
for (int u : child[p]) {
if (!dfn[u]) {
chi++;
int lowu = tarjan(p, u);
lowp = min(lowp, lowu);
if (lowu >= dfn[p])
iscut[p] = 1;
} else if (dfn[u] < dfn[p] && u != pa)
lowp = min(lowp, dfn[u]);
}
if (lowp == dfn[p]) {
cnt++;
int y;
do {
y = buff.back();
scc[cnt].push_back(y);
c[y] = cnt;
buff.pop_back();
} while (y != p);
}
if (pa == 0 && chi == 1) iscut[p] = 0;
return lowp;
}
int fa[maxn];
void dfs(int pa, int p) {
fa[p] = pa;
s[p] = siz[p];
for (int u : to[p]) {
if (u == pa) continue;
dfs(p, u);
s[p] += s[u];
}
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
child[u].push_back(v);
child[v].push_back(u);
}
tarjan(0, 1);
for (int i = 1; i <= cnt; i++)
for (int u : scc[i]) {
siz[i]++;
for (int v : child[u])
if (c[v] != i)
to[i].insert(c[v]);
}
dfs(0, 1);
for (int i = 1; i <= n; i++) {
if (!iscut[i]) {
cout << (n - 1) * 2 << "\n";
} else {
long long ans = 0, sum = 0;
con.clear();
for (int u : child[i]) con.insert(c[u]);
con.erase(c[i]);
for (int u : con) {
if (fa[c[i]] == u) {
ans += sum * (s[1] - s[c[i]]);
sum += s[1] - s[c[i]];
} else {
ans += sum * s[u];
sum += s[u];
}
}
cout << (ans + sum * (s[1] - sum - 1) + (n - 1)) * 2 << "\n";
}
}
}