[luogu] P3469 [POI2008]BLO-Blockade Tarjan判断割点

前言

传送门 :

思路

对于当前删除的点, 如果这个点不是割点的话,那么这个点给出的贡献就是 2 ∗ ( n − 1 ) 2*(n-1) 2(n1)

否则如果是割点的话 ,删除这个点,整个图将会变成多个连通块

因此对于每一个连通块的贡献又是 s z [ i ] ∗ ( n − s z [ i ] ) sz[i]*(n-sz[i]) sz[i](nsz[i])

因此计算即可 [判断割点传送门]

Code

const int N = 1e6+10;
int n,m;
int h[N],e[N*2],ne[N*2],idx;

ll ans[N];
int dfn[N],low[N],sz[N],tot;
int st[N];


void add(int a,int b){
	e[++idx] = b,ne[idx] = h[a] ,h[a] = idx;
}

void tarjan(int u){
	dfn[u] = low[u] = ++tot;
	sz[u] = 1;
	int flag= 0 , sum = 0;
	for(int i = h[u];i;i=ne[i]){
		int j = e[i];
		if(!dfn[j]){
			tarjan(j);
			sz[u]+=sz[j];
			low[u] = min(low[u],low[j]);
			if(low[j] >= dfn[u]){
				ans[u] += 1ll*sz[j]*(n-sz[j]);
				sum+=sz[j];
				flag ++;
				if(u!=1 || flag >1)st[u] = true;
			}
		}else low[u] = min(low[u],dfn[j]);
	}
	
	//如果是割点的话
	if(!st[u]) ans[u] = 2*(n-1);
	else ans[u]+=1ll*(n-sum-1)*(sum+1)+(n-1);
}
void solve(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int a,b;cin>>a>>b;
		add(a,b);add(b,a);
	}
	tarjan(1);
	for(int i=1;i<=n;i++) cout<<ans[i]<<endl;
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值