信息学奥赛一本通 4149:【GESP2509七级】连通图 | 洛谷 P14077 [GESP202509 七级] 连通图

【题目链接】

ybt 4149:【GESP2509七级】连通图
洛谷 P14077 [GESP202509 七级] 连通图

【题目难度】:E

【题目考点】

1. 图论:连通分量

连通分量:无向图中极大的连通子图。

求图中连通分量数量的方法:

  • 深搜广搜
  • 并查集

2. 并查集

【解题思路】

本题可以作为求连通分量的模板题。

将图中每个连通分量可以看作一个顶点(这是"缩点"思路),设有 c n t cnt cnt个顶点,那么要想让这 c n t cnt cnt个顶点之间互相连通,形成一个连通图,需要添加的边数最少为 c n t − 1 cnt-1 cnt−1,形成树型结构(无环连通无向图)。

问题变为求图中连通分量的数量 c n t cnt cnt。

解法1:深搜广搜

尝试从每个未访问过的顶点出发进行深搜或广搜,标记已访问的顶点。成功开始搜索的次数为连通分量的数量

解法2:并查集

将每个连通分量当做一个集合。如果顶点A到顶点B有一条无向边,则顶点A、B在同一个集合中,将A、B所在的集合合并。遍历所有的边后,统计集合的数量即为连通分量的数量。

【题解代码】

解法1:深搜广搜求连通分量

  • 写法1:深搜求连通分量
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
vector<int> g[N];
int n, m, cnt;
bool vis[N];
void dfs(int u)
{
	vis[u] = true;
	for(int v : g[u]) if(!vis[v])
		dfs(v);
}
int main()
{
	int u, v;
	cin >> n >> m;
	for(int i = 1; i <= m; ++i)
	{
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for(int i = 1; i <= n; ++i) if(!vis[i])
	{
		dfs(i);
		cnt++;
	}
	cout << cnt-1;
	return 0;
}
  • 写法2:广搜求连通分量
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
vector<int> g[N];
int n, m, cnt;
bool vis[N];
void bfs(int sv)
{
	queue<int> que;
	vis[sv] = true;
	que.push(sv);
	while(!que.empty())
	{
		int u = que.front();
		que.pop();
		for(int v : g[u]) if(!vis[v])
		{
			vis[v] = true;
			que.push(v);
		}
	}
}
int main()
{
	int u, v;
	cin >> n >> m;
	for(int i = 1; i <= m; ++i)
	{
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for(int i = 1; i <= n; ++i) if(!vis[i])
	{
		bfs(i);
		cnt++;
	}
	cout << cnt-1;
	return 0;
}

解法2:并查集求连通分量

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
int n, m, cnt, fa[N];
void init(int n)
{
	for(int i = 1; i <= n; ++i)
		fa[i] = i;
}
int find(int x)
{
	return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
	fa[find(x)] = find(y);
}
int main()
{
	int u, v;
	cin >> n >> m;
	init(n);
	for(int i = 1; i <= m; ++i)
	{
		cin >> u >> v;
		merge(u, v);
	}
	for(int i = 1; i <= n; ++i) if(fa[i] == i)
		cnt++;
	cout << cnt-1;
	return 0;
}
相关推荐
charlie1145141913 小时前
通用GUI编程技术——图形渲染实战(二十六)——GDI+与GDI架构差异:抗锯齿与渐变
c++·windows·学习·图形渲染·win32
我头发多我先学3 小时前
C++ STL list 原理到模拟实现
开发语言·c++·list
小肝一下3 小时前
每日两道力扣,day7
数据结构·c++·算法·leetcode·双指针·hot100·接雨水,四数之和
学嵌入式的小杨同学3 小时前
STM32 进阶封神之路(四十)FreeRTOS 队列、信号量、互斥锁精讲|任务通信、同步、资源保护(超详细图文版)
c++·stm32·单片机·嵌入式硬件·mcu·架构·硬件架构
2401_892070981 天前
【Linux C++ 日志系统实战】LogFile 日志文件管理核心:滚动策略、线程安全与方法全解析
linux·c++·日志系统·日志滚动
yuzhuanhei1 天前
Visual Studio 配置C++opencv
c++·学习·visual studio
不爱吃炸鸡柳1 天前
C++ STL list 超详细解析:从接口使用到模拟实现
开发语言·c++·list
十五年专注C++开发1 天前
RTTR: 一款MIT 协议开源的 C++ 运行时反射库
开发语言·c++·反射
‎ദ്ദിᵔ.˛.ᵔ₎1 天前
STL 栈 队列
开发语言·c++