现在给定一个 包含 n 个点 m条边的无向图,请你求出这个无向图中有多少连通块是" 树 "。 一个连通块是" 树 ",当且仅当图连通且边数比点数少 1 。1≤n≤10^5 ,0≤m≤min{n∗(n−1)/2,2×10^5 }。c++
时间: 2024-09-22 22:07:02 浏览: 294
这个问题是在问如何计算给定无向图中的连通分量,其中每个连通分量都是一个树形结构。由于树是一种特殊的图,其特点是有 n-1 条边(n 个顶点),并且任意两个顶点之间存在唯一的路径。为了找出有多少这样的“树”连通块,我们可以采用以下策略:
1. **使用并查集** (Disjoint-set data structure):首先将所有节点初始化到它们自身所在的集合中,然后遍历每一条边。对于每条边 (u, v),如果 u 和 v 属于不同的集合,就合并这两个集合,同时检查连接后的集合的大小。如果是 n - 1 (即点的数量减一),说明发现了一个树形连通块。
2. **遍历边的同时计数**:在合并集合的过程中,记录下找到的“树”个数。因为树有 n - 1 条边,所以如果在合并过程中发现集合的大小变成了 n,则说明找到了一个新的树连通块,计数加一。
3. **遍历结束后返回结果**:遍历完所有的边之后,统计的结果就是连通块中树的数量。
```cpp
#include <vector>
#include <unordered_set>
int countTrees(int n, std::vector<std::pair<int, int>>& edges) {
// 使用并查集存储节点及其集合信息
std::vector<int> parent(n, -1);
std::vector<int> rank(n, 0);
int treeCount = 0;
for (const auto& edge : edges) {
int u = edge.first, v = edge.second;
// 如果节点不在同一个集合中,合并,并更新树的数量
if (parent[u] != parent[v]) {
if (rank[parent[u]] > rank[parent[v]]) {
parent[v] = parent[u];
} else {
parent[u] = parent[v];
if (rank[parent[u]] == rank[parent[v]]) {
rank[parent[u]]++;
}
}
if (parent[u] == u && parent[v] == v) { // 检查是否形成新的树
if (rank[u] + rank[v] == n) {
treeCount++;
}
}
}
}
return treeCount;
}
```
阅读全文