P3469 [POI2008]BLO-Blockade tarjan割点

本文探讨了在图论中,如何通过Tarjan算法识别关键节点(割点),并计算禁止这些节点后对图中点间访问次数的影响。特别关注了如何在遍历时计算子树之间的贡献以及对除子树外节点的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:有n个点m条无向边,每个点要拜访其他所有点,总共有n*(n-1)次拜访次数。保证图联通,问禁止通行某个点后一共会少多少次拜访次数。输出n行,每行代表 i点禁止通行会减少的拜访次数。

解:如果这个点不影响图的联通性,则答案为2*(n-1),也即他不能到所有的n-1个点,n-1个点也不能到达他。

如果影响图的联通性,也就是割点,则答案再加上各个分量累乘之和,采用tarjan求割点时,由于是像树一样遍历,考虑子树之间对答案的贡献和所有子树之和对除子树外的点的贡献。求出的是单向的输出*2

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 100005;
int n,m,x,y,tot,tim;
int dfn[N],low[N],size[N],head[N],cut_point[N];
ll ans[N];
struct Edge{
	int to,nxt;
}edge[1000005];
void add(int x,int y){
	tot++;
	edge[tot].to = y;
	edge[tot].nxt = head[x];
	head[x] = tot;
}
int tarjan(int now){
	int z = 0;size[now] = 1;
	dfn[now] = low[now] = ++tim;
	for(int i=head[now];i;i=edge[i].nxt){
		int t = edge[i].to;
		if(!dfn[t]){
			tarjan(t);
			size[now]+=size[t];
			low[now] = min(low[now],low[t]);
			if(dfn[now]<=low[t]){
				ans[now]+=(ll)z*size[t];
				z+=size[t];
			}
		}else low[now] = min(low[now],dfn[t]);
	}
	ans[now]+=(ll)z*(n-z-1);
}
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d %d",&x,&y);
		add(x,y);
		add(y,x);
	}
	tarjan(1);
	for(int i=1;i<=n;i++){
		printf("%lld\n",(ans[i]+n-1)<<1);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wym_king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值