1 条题解
-
0
#include<bits/stdc++.h> using namespace std; // [1] 全局常量:最大数的限制,适配题目n≤1000的范围 const int MAXN = 1010; // [2] 全局数组:并查集父节点数组,存储每个数的父节点编号 int fa[MAXN]; // [3] 全局数组:并查集深度数组,用于按秩合并优化,避免树结构退化 int dep[MAXN]; // [13] 跳转至find函数:带路径压缩,查找节点x所在集合的根节点 int find(int x) { // [14] 函数参数x:待查找根节点的数的编号 if(x != fa[x]) { fa[x] = find(fa[x]); // [15] 路径压缩:直接将节点指向根节点,优化后续查询效率 } return fa[x]; // [16] 返回找到的根节点,用于判断两数是否属于同一集合 } // [17] find函数注释完成,返回主函数继续注释 // [20] 跳转至unite函数:按秩合并x和y所在的两个集合 void unite(int x, int y) { // [21] 函数参数x、y:待合并的两个数的编号 x = find(x); // [22] 查找x所在集合的根节点 y = find(y); // [23] 查找y所在集合的根节点 if(x == y) return; // [24] 两数已属于同一集合,无需重复合并 // [25] 按秩合并逻辑:将深度更小的树合并到深度更大的树下,保持树结构平衡 if(dep[x] > dep[y]) { fa[y] = x; } else if(dep[x] < dep[y]) { fa[x] = y; } else { fa[y] = x; dep[x]++; // [26] 两棵树深度相同时,合并后根节点深度+1 } } // [27] unite函数注释完成,返回主函数继续注释 // [4] 主函数:程序运行入口 int main() { int m, n; cin >> m >> n; // [5] 读入关系总数m、数的总个数n // [6] 循环初始化并查集,为每个数初始化集合状态 for(int i = 1; i <= n; i++) { fa[i] = i; // [7] 每个数初始独立为一个集合,父节点设为自身 dep[i] = 1; // [8] 每个集合的初始树深度设为1 } int redundantCnt = 0; // [9] 统计变量:记录多余关系的数量 // [10] 遍历所有m条关系,判断并统计多余数据 for(int i = 1; i <= m; i++) { int x, y; cin >> x >> y; // [11] 读入属于同一集合的两个数x、y // [12] 调用find函数判断x和y是否已属于同一集合,跳转至find函数注释 if(find(x) == find(y)) { // [17] 回到主函数if判断内的代码 redundantCnt++; // [18] 两数已连通,当前关系为多余数据,计数+1 } else { // [19] 调用unite函数合并x和y所在的集合,跳转至unite函数注释 unite(x, y); } } // [27] 回到主函数遍历关系后的代码 cout << redundantCnt << endl; // [28] 输出多余关系的总数 return 0; }
- 1
信息
- ID
- 1363
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者