就是点双连通分量的裸题,我们记录一个siz,如果某个点可以搜到low比它的deep值大的点的话,显然是产生了一个分割后的连通块。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#define pa pair<int,int>
#define inf 1000000000
#define ll long long
using namespace std;
inline void read(int &res){
int flag=1;static char ch;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
int n,m,cnt,tot;
int head[100005],size[100005],dfn[100005],low[100005];
ll ans[100005];
struct data{
int to,next;
}E[1000005];
void addedge(int u,int v){
E[++tot].to=v;E[tot].next=head[u];head[u]=tot;
E[++tot].to=u;E[tot].next=head[v];head[v]=tot;
}
void tarjan(int x){
int t=0;
size[x]=1;
dfn[x]=low[x]=++cnt;
for(int i=head[x];i;i=E[i].next)
if(dfn[E[i].to])low[x]=min(low[x],dfn[E[i].to]);
else{
tarjan(E[i].to);
size[x]+=size[E[i].to];
low[x]=min(low[x],low[E[i].to]);
if(dfn[x]<=low[E[i].to]){
ans[x]+=(ll)t*size[E[i].to];
t+=size[E[i].to];
}
}
ans[x]+=(ll)t*(n-t-1);
}
int main(){
read(n),read(m);
for(int u,v,i=1;i<=m;i++)
read(u),read(v),addedge(u,v);
tarjan(1);
for(int i=1;i<=n;i++)
printf("%lld\n",(ans[i]+n-1)*2);
return 0;
}