题目
解题思路
判断割点,然后对于每一个割点。
设被割的联通分量为A,剩余为B
那么统计答案为:A到B的点对数+A点内的经过A点的点对数/2+A点到其它点(n-1)
代码
#include<cstdio>
#include<algorithm>
#define N 50010
using namespace std;
struct node{
int y,next;
}a[N*4];
int head[N],tot,num=0,n,m,ans[N],dfn[N],A,B,low[N],siz[N]; bool v[N];
void add(int x,int y){a[++tot]=(node){y,head[x]}; head[x]=tot;}
void tarjan(int x,int fa){
dfn[x]=low[x]=++num;
int L=0;
for (int i=head[x];i;i=a[i].next){
int y=a[i].y; v[y]=0;
if (!dfn[y]){
tarjan(y,x);
siz[x]+=siz[y];
if (low[y]>=dfn[x]) L+=siz[y];
v[y]=1;
}
if (y!=fa) low[x]=min(low[x],low[y]);
}
B=A=0;
for (int i=head[x];i;i=a[i].next)
if (low[a[i].y]>=dfn[x]&&v[a[i].y]){
A+=(L-siz[a[i].y])*siz[a[i].y];
B+=(n-L-1)*siz[a[i].y];
}
A/=2;
ans[x]=B+A+n-1;
return;
}
int main(){
scanf("%d%d",&n,&m); int x,y;
for (int i=1;i<=m;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
for (int i=1;i<=n;i++) siz[i]=1;
tarjan(1,0);
for (int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}