1 条题解
-
0
#include<bits/stdc++.h> using namespace std; // [1] 全局常量:最大人数限制,适配题目N,M≤10000的范围 const int MAXN = 10010; // [2] 男性并查集数组:A公司(男性,正数编号)的父节点数组 int fa_male[MAXN]; // [3] 男性并查集深度数组:用于按秩合并优化 int dep_male[MAXN]; // [4] 女性并查集数组:B公司(女性,负数编号)的父节点数组,存储绝对值后的编号 int fa_female[MAXN]; // [5] 女性并查集深度数组:用于按秩合并优化 int dep_female[MAXN]; // 函数声明 int find_male(int x); void unite_male(int x, int y); int find_female(int x); void unite_female(int x, int y); // [6] 主函数:程序运行入口 int main() { int N, M, P, Q; cin >> N >> M >> P >> Q; // [7] 读入A公司人数N、B公司人数M、男性朋友关系数P、女性朋友关系数Q // [8] 初始化男性并查集 for(int i = 1; i <= N; i++) { fa_male[i] = i; // [9] 每个男性初始独立为一个集合,父节点设为自身 dep_male[i] = 1; // [10] 每个集合的初始树深度设为1 } // [11] 处理P条男性朋友关系 for(int i = 1; i <= P; i++) { int X, Y; cin >> X >> Y; // [12] 读入男性朋友的两个编号 // [13] 调用男性并查集合并函数,跳转至该函数完成注释 unite_male(X, Y); } // [20] 回到主函数,男性关系处理完成 // [21] 初始化女性并查集 for(int i = 1; i <= M; i++) { fa_female[i] = i; // [22] 每个女性初始独立为一个集合,父节点设为自身(编号取绝对值) dep_female[i] = 1; // [23] 每个集合的初始树深度设为1 } // [24] 处理Q条女性朋友关系 for(int i = 1; i <= Q; i++) { int X, Y; cin >> X >> Y; // [25] 读入女性朋友的两个负数编号 int a = abs(X); // [26] 负数编号取绝对值,适配数组下标 int b = abs(Y); // [27] 调用女性并查集合并函数,跳转至该函数完成注释 unite_female(a, b); } // [34] 回到主函数,女性关系处理完成 int cnt_male = 0; // [35] 统计变量:和小明(编号1)连通的男性人数 int root_male = find_male(1); // [36] 获取小明所在集合的根节点 // [37] 遍历所有男性,统计和小明同集合的人数 for(int i = 1; i <= N; i++) { if(find_male(i) == root_male) { cnt_male++; } } int cnt_female = 0; // [38] 统计变量:和小红(编号-1,绝对值1)连通的女性人数 int root_female = find_female(1); // [39] 获取小红所在集合的根节点 // [40] 遍历所有女性,统计和小红同集合的人数 for(int i = 1; i <= M; i++) { if(find_female(i) == root_female) { cnt_female++; } } // [41] 最多舞伴对数为男性人数和女性人数的最小值(一男一女配对) cout << min(cnt_male, cnt_female) << endl; return 0; // [42] 主函数正常结束 } // [14] 跳转至男性并查集find函数:带路径压缩,查找节点x的根节点 int find_male(int x) { // [15] 函数参数x:待查找根节点的男性编号 if(x != fa_male[x]) { fa_male[x] = find_male(fa_male[x]); // [16] 路径压缩:直接将节点指向根节点 } return fa_male[x]; // [17] 返回找到的根节点 } // [18] find_male函数注释完成,返回unite_male函数继续注释 // [19] 跳转至男性并查集unite函数:按秩合并x和y所在的两个集合 void unite_male(int x, int y) { // [19] 函数参数x、y:待合并的两个男性编号 x = find_male(x); y = find_male(y); if(x == y) return; // 两人已属于同一集合,无需重复合并 // 按秩合并逻辑:将深度更小的树合并到深度更大的树下 if(dep_male[x] > dep_male[y]) { fa_male[y] = x; } else if(dep_male[x] < dep_male[y]) { fa_male[x] = y; } else { fa_male[y] = x; dep_male[x]++; } } // [20] unite_male函数注释完成,返回主函数继续注释 // [28] 跳转至女性并查集find函数:带路径压缩,查找节点x的根节点 int find_female(int x) { // [29] 函数参数x:待查找根节点的女性编号(已取绝对值) if(x != fa_female[x]) { fa_female[x] = find_female(fa_female[x]); // [30] 路径压缩:直接将节点指向根节点 } return fa_female[x]; // [31] 返回找到的根节点 } // [32] find_female函数注释完成,返回unite_female函数继续注释 // [33] 跳转至女性并查集unite函数:按秩合并x和y所在的两个集合 void unite_female(int x, int y) { // [33] 函数参数x、y:待合并的两个女性编号(已取绝对值) x = find_female(x); y = find_female(y); if(x == y) return; // 两人已属于同一集合,无需重复合并 // 按秩合并逻辑:将深度更小的树合并到深度更大的树下 if(dep_female[x] > dep_female[y]) { fa_female[y] = x; } else if(dep_female[x] < dep_female[y]) { fa_female[x] = y; } else { fa_female[y] = x; dep_female[x]++; } } // [34] unite_female函数注释完成,返回主函数继续注释
- 1
信息
- ID
- 1368
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者