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
#include<cstdio>
int hea[100010],nxt[1000010],to[1000010],dfn[100010],low[100010],siz[100010],tot,num,n,m;
long long ans[100010];
void add(int a,int b)
{
nxt[++tot]=hea[a];
hea[a]=tot;
to[tot]=b;
}
void tarjan(int x,int rt)
{
dfn[x]=low[x]=++num;
siz[x]=1;
int f=0,cut=0,s=0;
for(int i=hea[x];i;i=nxt[i])
{
int y=to[i];
if(!dfn[y])
{
tarjan(y,rt);
siz[x]+=siz[y];
low[x]=low[x]<low[y]?low[x]:low[y];
if(low[y]>=dfn[x])
{
f++;
if(f>1||x!=rt)cut=1;
ans[x]=ans[x]+1ll*(n-siz[y])*siz[y];
//x是个割点,去掉它后
//它下面的子树Y中所有点,与图中其它点都不连通
s+=siz[y];
}
}
else low[x]=low[x]<dfn[y]?low[x]:dfn[y];
}
if(cut)
ans[x]=ans[x]+1ll*(n-s-1)*(s+1)+n-1;
//(n-s-1)代表去掉割点及它下面那些子树结点后,留下来的点
//这些点与这(s+1)个点不连通
//最后那个n-1是指x点本身与其它的所有点不连通
else
//如果x不是割点,则去掉它所有的边,它只与其它N-1个点不连通
ans[x]=2*n-2;
}
int main()
{
int x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
tarjan(1,1);
for(int i=1;i<=n;i++)
printf("%lld\n",ans[i]);
return 0;
}
原文:https://www.cnblogs.com/cutemush/p/12685928.html