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
一开始所有点互通,所以如果不是割点,那么只会有这个点到其他n-1个点无法互通,ans为(n-1)*2
如果是割点,则答案为它所分割的每一个连通分量两两相乘之和,在dfs时可以顺带求出来连通分量的大小,最后再加上它本身的n-1条路
#include<stdio.h>
#include<algorithm>
#define ll long long
#define N 100005
#define M 500005
using namespace std;
ll sum[N],siz[N],size;
int dfn[N],low[N];
bool cut[N];
int ind=0;
int n,m;
int head[N],num=0;
int root;
struct node
{
int to,next;
}e[M<<1];
void add(int u,int v)
{
e[++num].next=head[u],e[num].to=v;
head[u]=num;
}
void tarjan(int u,int fa)
{
int v;
dfn[u]=++ind;low[u]=ind;
int son=0;
siz[u]=1;ll size=0;
for(int i=head[u];i;i=e[i].next)
{
v=e[i].to;
if(!dfn[v])
{
tarjan(v,u);
siz[u]+=siz[v];
low[u]=min(low[v],low[u]);
if(low[v]>=dfn[u])
{
son++;
sum[u]+=1ll*siz[v]*size;
size+=siz[v];
if(u!=root || son>1)
cut[u]=true;
}
}
else
low[u]=min(low[u],dfn[v]);
}sum[u]+=1ll*size*(n-size-1);
}
void mainwork()
{
for(int i=1;i<=n;i++)
if(!dfn[i])
{
root=i;
tarjan(i,i);
}
}
int main()
{
scanf("%d%d",&n,&m);
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
root=1;
tarjan(1,1);
for(int i=1;i<=n;i++)
{
if(cut[i])
{
sum[i]=1LL*(sum[i]+n-1)*2;
printf("%lld\n",sum[i]);
}
else printf("%lld\n",1LL*(n-1)*2);
}
}