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
HINT
Source
只有割点会对答案有影响
通过乘法原理统计答案即可
#include<bits/stdc++.h>
using namespace std;
int n , m , linkk[101000] ,t;
int dfn[101000] , low[101000] , tot ;
long long son[101000];
bool check[101000];
int fa[101000];
struct node{
int n , y;
}e[1010000];
int read() {
bool flag=true;int num=0;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=false;
for(;c>='0'&&c<='9';c=getchar()) num=(num<<3)+(num<<1)+c-48;
if(flag) return num; else return -num;
}
void insert(int x,int y){
e[++t].y = y;e[t].n = linkk[x];linkk[x] = t;
e[++t].y = x;e[t].n = linkk[y];linkk[y] = t;
return;
}
void trajan(int x,int father){
fa[x] = father;
dfn[x] = low[x] = ++tot;
int flag = 0;
for(int i = linkk[x];i;i = e[i].n)
if(!dfn[e[i].y]){
int y = e[i].y;
trajan(y,x);
son[x] += son[y];
low[x] = min(low[x] , low[y]);
if(low[y] >= dfn[x]){
flag++;
if(x != 1 || flag > 1) check[x] = true;
}
}
else low[x] = min(low[x],dfn[e[i].y]);
son[x]++;
return;
}
void init(){
n = read();m = read();
for(int i = 1;i <= m;++i){
int x = read() , y = read();
insert( x , y );
}
trajan(1 , 0);
return;
}
void print(){
long long ans;
long long now;
for(int i = 1;i <= n;++i)
if(!check[i]) printf("%d\n",(n - 1) * 2);
else{
ans = 0;
now = 0;
for(int j = linkk[i];j;j = e[j].n){
int y = e[j].y;
if(fa[y] != i) continue;
if(low[y] >= dfn[i]) {
ans += 1ll * son[y] * ( n - son[y] - 1 );
now += son[y];
}
}
now = n - now - 1;
if(now != 0)
ans += now * ( n - now - 1 );
ans = ans + (n - 1) * 2;
printf("%lld\n",ans);
}
return;
}
void work(){
print();
return;
}
int main(){
init();
work();
// for(int i = 1;i <= n;++i)
// printf("%d ",dfn[i]);printf("\n");
// for(int i = 1;i <= n;++i)
// printf("%d ",low[i]);printf("\n");
return 0;
}