并查集

  • Post author:
  • Post category:其他




个人模板



基础版本(按「秩」(Rank)合并)

#include <vector>

using namespace std;

class Union{
public:
    int n;
    vector<int> parent;
    
    Union(int _n) {
        n = _n;
        parent.resize(n);
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }
    
    int find(int i) {
        if(parent[i] != i) {
            parent[i] = find(parent[i]);
        }
        return parent[i];
    }

    void _union(int i, int j) {
        int rootI = find(i);
        int rootJ = find(j);
        if(rootI != rootJ) {
            if(rootI > rootJ) { // 确保较小的作为根节点
                swap(rootI, rootJ);
            }
            parent[rootJ] = rootI;
        }
    }
};



优化版本(路径压缩)

#include <vector>

using namespace std;

class Union{
public:
    int n;
    vector<int> parent;
    
    Union(int _n) {
        n = _n;
        parent.resize(n);
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }
    
    int find(int i) {
        if(parent[i] != i) {
            parent[i] = find(parent[i]);
        }
        return parent[i];
    }

    void _union(int i, int j) {
        int rootI = find(i);
        int rootJ = find(j);
        if(rootI != rootJ) {
            if(rootI > rootJ) { // 确保较小的作为根节点
                swap(rootI, rootJ);
            }
            parent[rootJ] = rootI;
        }
    }
};



例题




547. 省份数量

class Union{
public:
    int n;
    vector<int> parent;
    
    Union(int _n) {
        n = _n;
        parent.resize(n);
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }
    
    int find(int i) {
    	int root = i;
    	while (root != parent[root]) {	// 找根节点
    		root = parent[root];
    	}
    	while (i != parent[i]) {	// 路径压缩
			int temp = parent[i];
			parent[i] = root;
			i = temp;
		}
        return root;
    }

    void _union(int i, int j) {
    	parent[find(i)] = find(j);
    }

};

class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        int n = isConnected.size();
        Union u(n);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                if (isConnected[i][j])
                    u._union(i,j);
            }
        }
        unordered_set<int> res;
        for (int i = 0; i < n; ++i) {
            res.insert(u.find(i));  // 注意此处是根节点,而不是单纯的节点
        }
        return res.size();
    }
};




684. 冗余连接

class Union{
public:
    int n;
    vector<int> parent;
    
    Union(int _n) {
        n = _n;
        parent.resize(n);
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }
    
    int find(int i) {
    	int root = i;
    	while (root != parent[root]) {	// 找根节点
    		root = parent[root];
    	}
    	while (i != parent[i]) {	// 路径压缩
			int temp = parent[i];
			parent[i] = root;
			i = temp;
		}
        return root;
    }

    void _union(int i, int j) {
    	parent[find(i)] = find(j);
    }

};

class Solution {
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        int n = edges.size();
        Union u(n+1);
        for (auto edge : edges) {
            int a = edge[0], b = edge[1];
            if (u.find(a) == u.find(b)) {
                return vector<int>{a,b};
            } else {
                u._union(a,b);
            }  
        }     
        return vector<int>();
    }
};




200. 岛屿数量

(未完成)




737.句子相似性II

(未完成)

给定两个句子 words1, words2 (每个用字符串数组表示),和一个相似单词对的列表 pairs ,判断是否两个句子是相似的。

例如,当相似单词对是 pairs = [[“great”, “fine”], [“acting”,“drama”], [“skills”,“talent”]]的时候,words1 = [“great”, “acting”, “skills”] 和 words2 = [“fine”, “drama”, “talent”] 是相似的。

注意相似关系是 具有 传递性的。

例如,如果 “great” 和 “fine” 是相似的,“fine” 和 “good” 是相似的,则 “great” 和 “good” 是相似的。

而且,相似关系是具有对称性的。

例如,“great” 和 “fine” 是相似的相当于 “fine” 和 “great” 是相似的。

并且,一个单词总是与其自身相似。

例如,句子 words1 = [“great”], words2 = [“great”], pairs = [] 是相似的,尽管没有输入特定的相似单词对。

最后,句子只会在具有相同单词个数的前提下才会相似。

所以一个句子 words1 = [“great”] 永远不可能和句子 words2 = [“doubleplus”,“good”] 相似。




1102. 得分最高的路径

(未完成)

给你一个 R 行 C 列的整数矩阵 A。矩阵上的路径从 [0,0] 开始,在 [R-1,C-1] 结束。

路径沿四个基本方向(上、下、左、右)展开,从一个已访问单元格移动到任一相邻的未访问单元格。

路径的得分是该路径上的 最小 值。例如,路径 8 → 4 → 5 → 9 的值为 4 。

找出所有路径中得分 最高 的那条路径,返回其 得分。

示例 1:

img

输入:[[5,4,5],[1,2,6],[7,4,6]]
输出:4
解释:
得分最高的路径用黄色突出显示。

示例 2:

img

输入:[[2,2,1,2,2,2],[1,2,2,2,1,2]]
输出:2

示例 3:

img

输入:[[3,4,6,3,4],[0,2,1,1,7],[8,8,3,2,7],[3,2,4,9,8],[4,1,2,0,0],[4,6,5,4,3]]
输出:3

提示:

1 <= R, C <= 100
0 <= A[i][j] <= 10^9




1135. 最低成本联通所有城市

(未完成)

想象一下你是个城市基建规划者,地图上有 N 座城市,它们按以 1 到 N 的次序编号。

给你一些可连接的选项 conections,其中每个选项 conections[i] = [city1, city2, cost] 表示将城市 city1 和城市 city2 连接所要的成本。(连接是双向的,也就是说城市 city1 和城市 city2 相连也同样意味着城市 city2 和城市 city1 相连)。

返回使得每对城市间都存在将它们连接在一起的连通路径(可能长度为 1 的)最小成本。该最小成本应该是所用全部连接代价的综合。如果根据已知条件无法完成该项任务,则请你返回 -1。

示例 1:

img

输入:N = 3, conections = [[1,2,5],[1,3,6],[2,3,1]]
输出:6
解释:
选出任意 2 条边都可以连接所有城市,我们从中选取成本最小的 2 条。

示例 2:

img

输入:N = 4, conections = [[1,2,3],[3,4,4]]
输出:-1
解释: 
即使连通所有的边,也无法连接所有城市。

提示:

1 <= N <= 10000
1 <= conections.length <= 10000
1 <= conections[i][0], conections[i][1] <= N
0 <= conections[i][2] <= 10^5
conections[i][0] != conections[i][1]




261. 以图判树

(未完成)

在这里插入图片描述




1061. 按字典序排列最小的等效字符串

(未完成)

在这里插入图片描述




323. 无向图中连通分量的数目

(未完成)

题目描述:

给定编号从

0



n-1



n

个节点和一个无向边列表(每条边都是一对节点),请编写一个函数来计算无向图中连通分量的数目。

示例:

示例 1:

输入: n = 5 和 edges = [[0, 1], [1, 2], [3, 4]]

     0          3
     |          |
     1 --- 2    4 

输出: 2

示例 2:

输入: n = 5 和 edges = [[0, 1], [1, 2], [2, 3], [3, 4]]

     0           4
     |           |
     1 --- 2 --- 3

输出:  1

注意:

你可以假设在 edges 中不会出现重复的边。而且由于所以的边都是无向边,[0, 1] 与 [1, 0] 相同,所以它们不会同时在 edges 中出现。




924. 尽量减少恶意软件的传播

(未完成)



版权声明:本文为XZ2585458279原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。