Description
Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。
Input
输入n<=100000 m<=500000及m条边
Output
输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。
思路:tarjan求割点模板,再用一下乘法原理,记得开long long
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, m, h[N], cnt;
int dfn[N], low[N], inde, cut[N], root, siz[N];
long long ans[N];
struct node {
int v, net;
} no[N];
void add(int u, int v) {
no[cnt].v = v;
no[cnt].net = h[u];
h[u] = cnt++;
}
void tarjan(int u) {
dfn[u] = low[u] = ++inde;
siz[u] = 1;
int f = 0, sum = 0;
for(int i = h[u]; ~i; i = no[i].net) {
int v = no[i].v;
if(!dfn[v]) {
tarjan(v);
siz[u] += siz[v];
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]) {
f++;
ans[u] += 1ll * siz[v] * (n - siz[v]);
sum += siz[v];
if(u != root || f > 1)
cut[u] = 1;
}
} else
low[u] = min(low[u], dfn[v]);
}
if(cut[u]) {
ans[u] += 1ll * (n - sum - 1) * (sum + 1) + (n - 1);
} else
ans[u] = 2 * (n - 1);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
memset(h, -1, sizeof h);
cin >> n >> m;
for(int x, y, i = 0; i < m; i++) {
cin >> x >> y;
if(x == y)
continue;
add(x, y), add(y, x);
}
for(int i = 1; i <= n; i++)
if(!dfn[i])
root = i, tarjan(i);
for(int i = 1; i <= n; i++)
cout << ans[i] << endl;
return 0;
}