Description
Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。
Input
输入n<=100000 m<=500000及m条边
Output
输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。
Sample Input
5 5
1 2
2 3
1 3
3 4
4 5
Sample Output
8
8
16
14
8
如果x不是割点,去掉它,就少了它与剩下(n-1)个点的连通,求少去多少有序对,(x,y)(y,x)算2对,所以有2*(n-1)对
如果x是割点,如图橙色的点是割点,它的根是绿色的点,有红色和黄色两个子树,去掉x,则会分成4中颜色,四个连通块。每个连通块去其他的点成有序对,所以在求割点时,求出每个连通块大小,size[s1](n-size[s1])+size[s2](n-size[s2])+……+(n-1)+(n-1-sum)*(1+sum)
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<queue>
#include<map>
#include<set>
#include<math.h>
#include<vector>
#include<set>
#define INF 0x3f3f3f3f
#define LL long long
#define mem(a, b) memset(a, b, sizeof(a))
#define N 100001
using namespace std;
int n, m, dfn[N], low[N], num, Size[N];
LL ans[N];
bool cut[N];
int ver[N*10], head[N], Next[N*10], tot;
void add(int x, int y) {
ver[++tot]=y, Next[tot]=head[x], head[x]=tot;
}
void tarjan(int x) {
dfn[x]=low[x]=++num, Size[x]=1;
int flag=0, sum=0;
for(int i=head[x]; i; i=Next[i]) {
int y=ver[i];
if(!dfn[y]) {
tarjan(y);
Size[x]+=Size[y];
low[x]=min(low[x], low[y]);
if(low[y]>=dfn[x]) {
flag++;
ans[x]+=(LL)(n-Size[y])*Size[y];
sum+=Size[y];//x的子节点个数
if(x!=1||flag>1) cut[x]=1;// 如果x不是根节点或者两个以上子节点满足条件,x的割点
}
}
else low[x]=min(low[x], dfn[y]);
}
if(cut[x])//如果x是割点
ans[x]+=(LL)(n-sum-1)*(sum+1)+n-1;
else
ans[x]=2*(n-1);
}
int main() {
scanf("%d%d",&n, &m);
for(int i=1; i<=m; i++) {
int x, y;
scanf("%d%d",&x, &y);
add(x, y), add(y, x);
}
tarjan(1);//因为所有的towns都连通
for(int i=1; i<=n; i++)
printf("%lld\n",ans[i]);
}