判断割点,然后对于每一个割点。
设被割的联通分量为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; }