信息学奥赛一本通 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;
}
相关推荐
星马梦缘18 分钟前
算法设计与分析 作业二 答案与解析
算法·图论·dfs·bfs·floyd-warshall·bellman_ford·多源最短路
样例过了就是过了38 分钟前
LeetCode热题100 分割等和子集
数据结构·c++·算法·leetcode·动态规划
麦兜和小可的舅舅1 小时前
ClickHouse 列管理机制解析:从 COW、IColumn 到 CRTP
c++·clickhouse
旖-旎1 小时前
深搜练习(组合)(5)
c++·算法·深度优先·力扣
vegetablesssss2 小时前
vtk镜像图
c++·qt·vtk
@小码农2 小时前
2026年3月Scratch图形化编程等级考试一级真题试卷
开发语言·数据结构·c++·算法
【 】4232 小时前
C++&STL(Standard Template Library,标准模板库)
java·开发语言·c++
一只牛_0073 小时前
pthread亲和性继承的一个坑:main绑核让整个进程退化到单核
c++
张健11564096483 小时前
C++访问控制与友元
java·开发语言·c++
BirdenT4 小时前
20260424紫题训练
c++·算法