当前位置: 首页 > news >正文

信息学奥赛一本通 1526:Blockade | 洛谷 P3469 [POI 2008] BLO-Blockade

【题目链接】

ybt 1526:Blockade
洛谷 P3469 [POI 2008] BLO-Blockade

【题目考点】

1. 图论:割点

【解题思路】

对于一个有n个顶点的无向连通图,问去掉每个顶点后,会有多少个有序点对(x, y),x与y不连通,也就是x到y没有路径。
看有序点对,那么(x, y)与(y, x)就是两个不同的点对。
设此时删除与顶点i相连的边,那么考虑第一个顶点为i的点对(i, x),另一个顶点x可以是除顶点i以外的任意顶点,共有n-1种可能。那么第一个顶点为i的点对(i, x)有n-1个。

如果顶点i不是割点,那么去掉与顶点i相连的边后,其余各顶点互相连通,因此互不连通的点对只有第二个顶点为i的点对(x, i),第一个顶点有n-1种情况,这样的点对有n-1个。
如果顶点i是割点,那么去掉与顶点i相连的边后,将整个图分成了多个连通分量。
设某个连通分量的顶点数为c,其余顶点数为n-c。该连通分量中的每个顶点与连通分量外的每个顶点都是互不连通的,因此以该连通分量内顶点为第一个顶点的点对有 c ( n − c ) c(n-c) c(nc)个。
因此需要求出删除割点后形成的每个连通分量中的顶点数量。而后将每个连通分量中的顶点数量c乘以剩余顶点数n-c后加和 ∑ c ( n − c ) \sum c(n-c) c(nc),即可得到所有的不连通点对的数量。

考察求割点的tarjan算法,该算法为dfs算法,搜索的同时也在构建dfs生成树。
对于某割点u,若访问邻接点v时v没有被访问过,那么在dfs生成树中v是u的孩子,边(u,v)是树边。
在这里插入图片描述

  • 如果满足条件“u是根且有两个以上的孩子,或dfn[u] <= low[v]”,那么u是割点。去掉顶点u后,dfs生成树中以v为根的子树就是一个连通分量。
    siz[u]表示dfs生成树中以u为根的树的顶点数,根据树形动规,siz[u]初值设为1,每搜索完一个u的孩子v,将siz[u]加上以顶点v为根的子树的顶点数siz[v],即siz[u] += siz[v]
    当满足dfn[u] <= low[v]时,以v为根的子树的顶点数是siz[v],该连通分量中顶点作为第一个顶点,该连通分量外顶点作为第二个顶点构成的顶点的顶点对有siz[v]*(n-siz[v])个。
  • dfs生成树中u的双亲,记为f。dfs生成树中u的孩子v还有不满足割点条件dfn[u] <= low[v]的顶点,这样的顶点记为v’,满足dfn[u] > low[v'],dfs生成树中一定存在从顶点v’一定有到达u的祖先的回边。因此在删掉顶点u的所有相连边后,所有以v’为根的子树和u的上方子树(dfs生成树中除了以u为根的子树之外的树)是连通的,形成一个连通分量。
    对于所有满足dfn[u] <= low[v]的顶点v,统计siz[v]的加和,记为sizChild。
    u的上方子树所在连通分量的顶点数是总顶点数减去其他每个连通分量的顶点数,再减去1(顶点u),即n-sizeChild-1。
    该连通分量中顶点为第一个顶点,该连通分量外顶点为第二个顶点的顶点对的数量为(n-sizeChild-1)*(n-(n-sizeChild-1))=(n-sizeChild-1)*(sizeChild+1)
    如果u不是割点,那么sizeChild为0,上式的值为n-1,和“如果顶点u不是割点,第二个顶点为u”的顶点对数相同。因此不需要判断u是否为割点,直接加上上式的值即可。

将删除顶点u相连的边产生的所有的有序点对数量加到结果a[u]中。最后输出数组a中的每个数。

【题解代码】

解法1:求割点

#include <bits/stdc++.h>
using namespace std;
#define N 100005
int n, m, dfn[N], low[N], ts, root;
long long ans[N], siz[N];
bool cutVer[N];
vector<int> edge[N];
void tarjan(int u)
{
	int child = 0, sizChild = 0;
	siz[u] = 1;//siz[u]:dfs生成树中以u为根的子树的大小 
	dfn[u] = low[u] = ++ts;
	for(int v : edge[u])
	{
		if(dfn[v] == 0)
		{
			tarjan(v);
			siz[u] += siz[v];
			low[u] = min(low[u], low[v]);
			if(u == root && ++child > 1 || u != root && dfn[u] <= low[v])
			{
				cutVer[u] = true;
				sizChild += siz[v];//sizChild:去掉割点u后,能单独成为一个连通分量的子树的大小加和 
				ans[u] += siz[v]*(n-siz[v]);
			}
		}
		else
			low[u] = min(low[u], dfn[v]);
	}
	ans[u] += (long long)(n-sizChild-1)*(sizChild+1)+n-1;//n-1为第一个顶点为u的数对数量
}
int main()
{
	int a, b;
	cin >> n >> m;
	for(int i = 1; i <= m; ++i)
	{
		cin >> a >> b;
		edge[a].push_back(b);
		edge[b].push_back(a);
	}
	tarjan(root = 1);//连通图 只需要进行一遍tarjan 
	for(int i = 1; i <= n; ++i)
		cout << ans[i] << '\n';
	return 0;
}

相关文章:

  • 2024年 蓝桥杯 Python A组题目分析与讲解
  • 新造车不再比拼排名,恰是曲终人散时,剩者为王
  • 从PLC到云端:5G嵌入式网关的MQTT协议转换与Ubuntu二次开发全解析
  • 用VSCode做前端开发
  • BFGS学习
  • 第四章:ESP32零基础教学 - 4.1.4MPU6050加速度传感器
  • 电机控制常见面试问题(十五)
  • 103. 水流问题
  • Dify 问题 - RAG Workflow 没有返回知识库引用
  • 为什么渲染农场渲染帧而非视频?核心原因 + 举例
  • 鸿蒙开源硬件:重构万物智联生态的底层基座与未来机遇
  • 单元化架构在字节跳动的落地实践
  • 【第13节】windows sdk编程:GDI编程
  • 从pdf提取文本数据的c/cpp库(非OCR)
  • 应用分层简介
  • 压缩Docker虚拟磁盘空间CMD命令
  • ssm框架之mybatis框架动态SQL
  • Modern C++处理 Hooks 机制
  • 解决Java多张图合成JPG时出现红色前景及多列自适应适配
  • 《基于Spring Boot+Vue的智慧养老系统的设计与实现》开题报告
  • 波兰总统选举投票开始,将是对亲欧路线的一次严峻考验
  • 江苏疾控:下设部门无“病毒研究所”,常荣山非本单位工作人员
  • 经济日报金观平:促进信贷资金畅达小微企业
  • 新城悦服务:独董许新民辞任,新任独董与另两人组成调查委员会将调查与关联方资金往来
  • 全国省市县国土空间总体规划已基本批复完成,进入全面实施阶段
  • 国税总局上海市税务局通报:收到王某对刘某某及相关企业涉税问题举报,正依法依规办理