并查集

冗余连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class Solution {
public:
static const int N = 1010;
int p[N], indegree[N], n;

int find(int x) { // 查找x的祖宗节点
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}

bool assertRemove(vector<vector<int>>&edges, int idx) {
// 建立并查集的过程中检查删除该边后是否还有环
for (int i = 0; i < n; ++ i) { // 遍历边集
if (i == idx) continue; // 排除该边
if (find(edges[i][0]) == find(edges[i][1]))
return false;
p[find(edges[i][0])] = find(edges[i][1]);
}
return true;
}

vector<int> remove(vector<vector<int>> &edges) {

for (int i = 0; i < n; ++ i) {
if (find(edges[i][0]) == find(edges[i][1]))
return edges[i];
p[find(edges[i][0])] = find(edges[i][1]);
}
return {};
}
vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
n = size(edges);
vector<int> vec;
for (int i = 1; i <= n; ++ i) p[i] = i;// 初始化并查集

// 查看是否有入度为2的点
for (int i = 0; i < n; ++ i)
++ indegree[edges[i][1]];
for (int i = n - 1; i >= 0; -- i) { // 逆序是有多个答案时删除较后的答案
if (indegree[edges[i][1]]==2)
vec.push_back(i);//保存节点对
}

// 如果有入度为2的点,则只需删除其中一条
if (vec.size()) {
if (assertRemove(edges, vec[0]))
return edges[vec[0]];
else
return edges[vec[1]];
}

// 没有入度为2的点,直接查找成环的边并删除
return remove(edges);
}
};

朋友圈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
public:
int p[210];

int find(int x) {
// 递归压缩路径
// if (x != p[x]) p[x] = find(p[x]);
// return p[x];
// 迭代压缩路径
int q = x, tmp;
while (p[q] != q) q = p[q]; // x的祖宗
while (x != q) { // 再从x开始查一遍,顺便把所有经过的节点祖宗更改。
tmp = p[x], p[x] = q, x = tmp;
}
return x;
}

int findCircleNum(vector<vector<int>>& M) {
int n = size(M);
for (int i = 0; i < n; ++ i) p[i] = i;

for (int i = 0; i < n; ++ i) {
for (int j = i; j < n; ++ j) {
if (M[i][j] == 1)
p[find(i)] = find(j);
}
}
int cnt = 0;
for (int i = 0; i < n; ++ i){
if (i == p[find(i)]) ++ cnt;
}
return cnt ;
}
};

等式方程的可满足性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public:
int p[30];

int find(int x) {
int q = x, tmp;
while (q != p[q]) q = p[q];
while (x != q) tmp = p[x], p[x] = q, x = tmp;
return x;
}

bool equationsPossible(vector<string>& equations) {
vector<int> unequ;
int n = size(equations);
for (int i = 0; i < 30; ++ i) {
p[i] = i;
}

for (int i = 0; i < n; ++ i) {
if (equations[i][1] == '=') {
p[find(equations[i][0]-'a')] = find(equations[i][3]-'a');
}else {
unequ.push_back(i);
}
}

for (const auto &i : unequ) {
if (find(equations[i][0]-'a') == find(equations[i][3]-'a'))
return false;
}
return true;
}
};