信息学奥赛一本通 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;
}
相关推荐
做人求其滴11 小时前
面试经典 150 题 380 274
c++·算法·面试·职场和发展·力扣
见叶之秋11 小时前
C++基础入门指南
开发语言·c++
计算机安禾11 小时前
【c++面向对象编程】第42篇:模板特化与偏特化:为特定类型定制实现
开发语言·c++·算法
玖釉-11 小时前
C++ 中的循环语句详解:while、do...while、for、嵌套循环与循环控制
开发语言·c++·算法
欧米欧12 小时前
C++进阶数据结构之搜索二叉树
开发语言·数据结构·c++
青小莫12 小时前
C++之vector讲解
c++·stl
计算机安禾13 小时前
【c++面向对象编程】第41篇:函数模板与类模板:泛型编程的基石
开发语言·c++·算法
一条大祥脚13 小时前
2021-2022 ICPC Southwestern Europe Regional Contest
算法·深度优先·图论
郝学胜-神的一滴14 小时前
Qt 高级开发 010: 从跨界面传值到自定义信号
开发语言·c++·qt·程序人生·用户界面
天若有情67314 小时前
自研极简C++软交互事件系统:干掉观察者模式、碾压前端事件机制
c++·观察者模式·交互·事件