https://leetcode-cn.com/problems/number-of-provinces/
.https://www.nowcoder.com/test/question/done?tid=48978417&qid=1795704#summary
力扣547:
class UnionFind{
public:
int find(int x){
int root = x;
while(father[root] != -1){
root = father[root];
}
//其实在这里已经找到了root了,下面这一步其实是路径压缩
while(x != root){
int original_father = father[x];
father[x] = root;
x = original_father;//去让自己的爸爸参与压缩,这样可以压缩很多个节点
//实现许多的节点以度为1指向这个根
}
return root;
}
bool is_connected(int x,int y){
return find(x) == find(y);//压缩路径
}
void merge(int x,int y){
int root_x = find(x);//每一次merge都会动态的压缩路径
int root_y = find(y);
if(root_x != root_y){
father[root_x] = root_y;
num_of_sets--;
}
}
void add(int x){
if(!father.count(x)){
father[x] = -1;
num_of_sets++;
}
}
int get_num_of_sets(){
return num_of_sets;
}
private:
// 记录父节点
unordered_map<int,int> father;
// 记录集合数量
int num_of_sets = 0;
};
class Solution {
public:
int findCircleNum(vector<vector<int>>& isConnected) {
UnionFind uf;
for(int i = 0;i < isConnected.size();i++){
uf.add(i);
for(int j = 0;j < i;j++){//保证了j比i小,说明j已经是建好的
if(isConnected[i][j]){
uf.merge(i,j);
}
}
}
return uf.get_num_of_sets();
}
};
2021腾讯校招
现在有107个用户,编号为1- 107,现在已知有m对关系,每一对关系给你两个数x和y,代表编号为x的用户和编号为y的用户是在一个圈子中,例如:A和B在一个圈子中,B和C在一个圈子中,那么A,B,C就在一个圈子中。现在想知道最多的一个圈子内有多少个用户。
输入描述:
第一行输入一个整数T,接下来有T组测试数据。
对于每一组测试数据:第一行输入1个整数n,代表有n对关系。
接下来n行,每一行输入两个数x和y,代表编号为x和编号为y的用户在同一个圈子里。
1 ≤ T ≤ 10
1 ≤ n ≤ 105
1 ≤ x, y ≤ 107
输出描述:
对于每组数据,输出一个答案代表一个圈子内的最多人数
输入例子1:
2
4
1 2
3 4
5 6
1 6
4
1 2
3 4
5 6
7 8
#include <bits/stdc++.h>
#include<iostream>
using namespace std;
#include"unordered_map"
class Union {
public:
Union() {
children.resize(10000000, 0);
}
void merge(int x, int y) {
int root_x = find(x);
int root_y = find(y);
if (root_x != root_y) {
father[root_x] = root_y;
children[root_y]=children[root_x]+1+children[root_y];
//得放在里面,两个一样就不用减了
num_union--;
}
}
int inconnect(int x, int y) {
return find(x) == find(y);
}
int find(int x) {
int root = x;
while (father[root] != -1) {//根节点的father是-1,不指向其他人
root = father[root];
}
if (root == x) return root;
//压缩
while (father[x] != root) {//就这一行写 while(father[x]!=root)就tl了....
//你想想看如果输入一个根节点,不就死循环了么,那么我们可以在上面判断是不是根节点,是就不用压缩了
int temp = father[x];
father[x] = root;
//children[root]++;
x = temp;
}
return root;
}
void add(int x) {
//记得特判
if (!father.count(x)) {
father[x] = -1;
num_union++;
}
}
int get_num() {
return num_union;
}
int get_a_union_num(int root) {//得到这个以root为根的群的数量
// cout<< children[root]<<endl;
return children[root]+1;
}
public:
unordered_map<int, int>father;
int num_union = 0;
vector<int>children;
};
int main() {
int n;
cin >> n;
while (n > 0) {
Union k;
int num;
int ans = -10;
cin >> num;
for (int i = 1; i <= num; i++) {
int a, b;
cin >> a >> b;
k.add(a);
k.add(b);
k.merge(a, b);//以最后加入这个为根
ans=max(ans,k.get_a_union_num(k.find(a)));
}
cout << ans << endl;
n--;
}
}
六大基本操做:
1.查根
2.查询是否在一个union
3.合并
4.增加节点
5.返回union数量