本文参照AcWing cornerCao同学的讲解,整理了一下并查集的模板和3道经典题目的实现。
并查集模板
class UnionFind{
public:
vector<int> father;
UnionFind(int num){ //num表示元素的个数
for(int i = 0; i < num; i++){
father.push_back(i); //箭头指向自己
}
}
int Find(int n){
//递归
if(father[n] == n)
return n;
father[n] = Find(father[n]); //路径压缩版本
return father[n];
}
void Union(int a, int b){
int fa = Find(a);
int fb = Find(b);
father[fb] = fa;
}
};
经典题目 1:leetcode 547. 朋友圈
class UnionFind{
public:
vector<int> father;
UnionFind(int num){
for(int i = 0; i < num; i++){
father.push_back(i);
}
}
int Find(int n){
if(father[n] == n)
return n;
father[n] = Find(father[n]);
return father[n];
}
void Union(int a, int b){
int fa = Find(a);
int fb = Find(b);
father[fb] = fa;
}
};
class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
int N = M.size();
UnionFind UF(N);
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
if(M[i][j]){
UF.Union(i, j);
}
}
}
int res = 0;
for(int i = 0; i < N; i++){
if(UF.Find(i) == i)
res++;
}
return res;
}
};
经典题目 2:leetcode 200. 岛屿的个数
class UnionFind{
public:
vector<int> father;
UnionFind(int num){
for(int i = 0; i < num; i++){
father.push_back(i);
}
}
int Find(int n){
if(father[n] == n)
return n;
father[n] = Find(father[n]);
return father[n];
}
void Union(int a, int b){
int fa = Find(a);
int fb = Find(b);
father[fb] = fa;
}
};
class Solution {
public:
int encode(int i, int j, int n){
return i * n + j;
}
int numIslands(vector<vector<char>>& grid) {
int M = grid.size();
if(M == 0)
return 0;
int N = grid[0].size();
if(N == 0)
return 0;
int directions[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
UnionFind UF(M * N);
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
if(grid[i][j] == '1'){
for(int d = 0; d < 4; d++){
int di = directions[d][0];
int dj = directions[d][1];
if(i + di >= 0 && i + di < M && j + dj >= 0 && j + dj < N && grid[i+di][j+dj] == '1'){
UF.Union(encode(i, j, N), encode(i + di, j + dj, N));
}
}
}
}
}
int res = 0;
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
if(grid[i][j] == '1' && UF.Find(encode(i, j, N)) == encode(i, j, N))
res++;
}
}
return res;
}
};
经典题目 3:leetcode 684. 冗余连接
class UnionFind{
public:
vector<int> father;
UnionFind(int num){
for(int i = 0; i < num; i++){
father.push_back(i);
}
}
int Find(int n){
if(father[n] == n)
return n;
father[n] = Find(father[n]);
return father[n];
}
bool Union(int a, int b){
int fa = Find(a);
int fb = Find(b);
father[fb] = fa;
return fa == fb;
}
};
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
int N = edges.size();
UnionFind UF(N + 1);
vector<int> res(2, 0);
for(int i = 0; i < edges.size(); i++){
int u = edges[i][0];
int v = edges[i][1];
if(UF.Union(u, v)){
res[0] = u;
res[1] = v;
}
}
return res;
}
};