[bzoj1123] [POI2008]BLO

Description
n个点m条边的无向连通图,无重边无自环.
求对于所有i,去掉第i个点后有多少对有序点不连通.
HINT
\(n\leq100000,m\leq500000\).
Solution
tarjan求割点的时候顺便计数即可.

#define N 100005
#define M 1000005
typedef long long ll;
struct graph{
	int nxt,to;
}e[M];
ll ans[N];
int g[N],dfn[N],low[N],siz[N],n,m,cnt;
bool cut[N];
inline void tarjan(int u,int fa){
	int chl=0,tot=0;
	dfn[u]=low[u]=++cnt;siz[u]=1;
	for(int i=g[u],c;i;i=e[i].nxt)
		if(!dfn[c=e[i].to]){
			tarjan(c,u);
			siz[u]+=siz[c];
			low[u]=min(low[u],low[c]);
			if(!fa){
				if(++chl>=2){
					cut[u]=true;
					ans[u]+=1ll*siz[c]*tot;
					tot+=siz[c];
				}
			}
			else if(low[c]>=dfn[u]){
				cut[u]=true;
				ans[u]+=1ll*siz[c]*tot;
				tot+=siz[c];
			}
		}
		else if(c!=fa)
			low[u]=min(low[u],dfn[c]);
	if(cut[u]) ans[u]+=1ll*(n-1-tot)*tot;
	ans[u]+=n-1;
}
inline void addedge(int x,int y){
	e[++cnt]=(graph){g[x],y};g[x]=cnt;
}
inline void Aireen(){
	n=read();m=read();
	for(int i=1,x,y;i<=m;++i){
		x=read();y=read();
		addedge(x,y);addedge(y,x);
	}
	for(int i=1;i<=n;++i)
		if(!dfn[i]) tarjan(i,0);
	for(int i=1;i<=n;++i)
		printf("%lld\n",ans[i]<<1);
}

2017-10-27 13:11:29

原文地址:https://www.cnblogs.com/AireenYe/p/bzoj1123.html