Skip to content

Commit fbc7213

Browse files
committed
feat: add solutions to lc problem: No.1579.Remove Max Number of Edges to
Keep Graph Fully Traversable
1 parent 4d61653 commit fbc7213

File tree

6 files changed

+677
-38
lines changed

6 files changed

+677
-38
lines changed

solution/1500-1599/1579.Remove Max Number of Edges to Keep Graph Fully Traversable/README.md

+272-2
Original file line numberDiff line numberDiff line change
@@ -59,27 +59,297 @@
5959
<li>所有元组 <code>(type<sub>i</sub>, u<sub>i</sub>, v<sub>i</sub>)</code> 互不相同</li>
6060
</ul>
6161

62-
6362
## 解法
6463

6564
<!-- 这里可写通用的实现逻辑 -->
6665

66+
并查集。
67+
68+
模板 1——朴素并查集:
69+
70+
```python
71+
# 初始化,p存储每个点的父节点
72+
p = list(range(n))
73+
# 返回x的祖宗节点
74+
def find(x):
75+
if p[x] != x:
76+
# 路径压缩
77+
p[x] = find(p[x])
78+
return p[x]
79+
# 合并a和b所在的两个集合
80+
p[find(a)] = find(b)
81+
```
82+
83+
模板 2——维护 size 的并查集:
84+
85+
```python
86+
# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量
87+
p = list(range(n))
88+
size = [1] * n
89+
# 返回x的祖宗节点
90+
def find(x):
91+
if p[x] != x:
92+
# 路径压缩
93+
p[x] = find(p[x])
94+
return p[x]
95+
# 合并a和b所在的两个集合
96+
if find(a) != find(b):
97+
size[find(b)] += size[find(a)]
98+
p[find(a)] = find(b)
99+
```
100+
101+
模板 3——维护到祖宗节点距离的并查集:
102+
103+
```python
104+
# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离
105+
p = list(range(n))
106+
d = [0] * n
107+
# 返回x的祖宗节点
108+
def find(x):
109+
if p[x] != x:
110+
t = find(p[x])
111+
d[x] += d[p[x]]
112+
p[x] = t
113+
return p[x]
114+
# 合并a和b所在的两个集合
115+
p[find(a)] = find(b)
116+
d[find(a)] = distance
117+
```
118+
119+
对于本题,构造两个并查集。同时操作两个并查集 ufa, ufb,优先添加 `type = 3` 的边,添加的过程中,若两点已连通,则累加多余的边 res。
120+
121+
然后遍历 `type = 1` 的边添加到 ufa 中,而 `type = 2` 的边则添加到 ufb 中。此过程同样判断两点是否已连通,若是,则累加多余的边 res。
122+
123+
最后判断两个并查集是否都只有一个连通分量,若是,返回 res,否则返回 -1。
124+
67125
<!-- tabs:start -->
68126

69127
### **Python3**
70128

71129
<!-- 这里可写当前语言的特殊实现逻辑 -->
72130

73131
```python
74-
132+
class UnionFind:
133+
def __init__(self, n):
134+
self.p = list(range(n))
135+
self.n = n
136+
137+
def union(self, a, b) -> bool:
138+
pa, pb = self.find(a - 1), self.find(b - 1)
139+
if pa == pb:
140+
return False
141+
self.p[pa] = pb
142+
self.n -= 1
143+
return True
144+
145+
def find(self, x) -> int:
146+
if self.p[x] != x:
147+
self.p[x] = self.find(self.p[x])
148+
return self.p[x]
149+
150+
class Solution:
151+
def maxNumEdgesToRemove(self, n: int, edges: List[List[int]]) -> int:
152+
ufa, ufb = UnionFind(n), UnionFind(n)
153+
res = 0
154+
for t, u, v in edges:
155+
if t == 3:
156+
if not ufa.union(u, v):
157+
res += 1
158+
else:
159+
ufb.union(u, v)
160+
for t, u, v in edges:
161+
if t == 1:
162+
if not ufa.union(u, v):
163+
res += 1
164+
elif t == 2:
165+
if not ufb.union(u, v):
166+
res += 1
167+
return res if ufa.n == 1 and ufb.n == 1 else -1
75168
```
76169

77170
### **Java**
78171

79172
<!-- 这里可写当前语言的特殊实现逻辑 -->
80173

81174
```java
175+
class Solution {
176+
public int maxNumEdgesToRemove(int n, int[][] edges) {
177+
UnionFind ufa = new UnionFind(n);
178+
UnionFind ufb = new UnionFind(n);
179+
int res = 0;
180+
for (int[] e : edges) {
181+
if (e[0] == 3) {
182+
if (!ufa.union(e[1], e[2])) {
183+
++res;
184+
} else {
185+
ufb.union(e[1], e[2]);
186+
}
187+
}
188+
}
189+
for (int[] e : edges) {
190+
if (e[0] == 1) {
191+
if (!ufa.union(e[1], e[2])) {
192+
++res;
193+
}
194+
} else if (e[0] == 2) {
195+
if (!ufb.union(e[1], e[2])) {
196+
++res;
197+
}
198+
}
199+
}
200+
return ufa.n == 1 && ufb.n == 1 ? res : -1;
201+
}
202+
}
203+
204+
class UnionFind {
205+
public int[] p;
206+
public int n;
207+
208+
public UnionFind(int n) {
209+
p = new int[n];
210+
for (int i = 0; i < n; ++i) {
211+
p[i] = i;
212+
}
213+
this.n = n;
214+
}
215+
216+
public boolean union(int a, int b) {
217+
int pa = find(a - 1), pb = find(b - 1);
218+
if (pa == pb) {
219+
return false;
220+
}
221+
p[pa] = pb;
222+
--n;
223+
return true;
224+
}
225+
226+
public int find(int x) {
227+
if (p[x] != x) {
228+
p[x] = find(p[x]);
229+
}
230+
return p[x];
231+
}
232+
}
233+
```
234+
235+
### **C++**
236+
237+
```cpp
238+
class UnionFind {
239+
public:
240+
vector<int> p;
241+
int n;
242+
243+
UnionFind(int _n): n(_n), p(_n) {
244+
iota(p.begin(), p.end(), 0);
245+
}
246+
247+
bool unite(int a, int b) {
248+
int pa = find(a - 1), pb = find(b - 1);
249+
if (pa == pb)
250+
return false;
251+
p[pa] = pb;
252+
--n;
253+
return true;
254+
}
255+
256+
int find(int x) {
257+
if (p[x] != x)
258+
p[x] = find(p[x]);
259+
return p[x];
260+
}
261+
};
262+
263+
class Solution {
264+
public:
265+
int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {
266+
UnionFind ufa(n), ufb(n);
267+
int res = 0;
268+
for (auto e : edges)
269+
{
270+
if (e[0] == 3)
271+
{
272+
if (!ufa.unite(e[1], e[2])) ++res;
273+
else ufb.unite(e[1], e[2]);
274+
}
275+
}
276+
for (auto e : edges)
277+
{
278+
if (e[0] == 1)
279+
{
280+
if (!ufa.unite(e[1], e[2])) ++res;
281+
}
282+
else if (e[0] == 2)
283+
{
284+
if (!ufb.unite(e[1], e[2])) ++res;
285+
}
286+
}
287+
return ufa.n == 1 && ufb.n == 1 ? res : -1;
288+
}
289+
};
290+
```
82291
292+
### **Go**
293+
294+
```go
295+
type unionFind struct {
296+
p []int
297+
n int
298+
}
299+
300+
func newUnionFind(n int) *unionFind {
301+
p := make([]int, n)
302+
for i := range p {
303+
p[i] = i
304+
}
305+
return &unionFind{p, n}
306+
}
307+
308+
func (uf *unionFind) find(x int) int {
309+
if uf.p[x] != x {
310+
uf.p[x] = uf.find(uf.p[x])
311+
}
312+
return uf.p[x]
313+
}
314+
315+
func (uf *unionFind) union(a, b int) bool {
316+
pa, pb := uf.find(a-1), uf.find(b-1)
317+
if pa == pb {
318+
return false
319+
}
320+
uf.p[pa] = pb
321+
uf.n--
322+
return true
323+
}
324+
325+
func maxNumEdgesToRemove(n int, edges [][]int) int {
326+
ufa, ufb := newUnionFind(n), newUnionFind(n)
327+
res := 0
328+
for _, e := range edges {
329+
if e[0] == 3 {
330+
if !ufa.union(e[1], e[2]) {
331+
res++
332+
} else {
333+
ufb.union(e[1], e[2])
334+
}
335+
}
336+
}
337+
for _, e := range edges {
338+
if e[0] == 1 {
339+
if !ufa.union(e[1], e[2]) {
340+
res++
341+
}
342+
} else if e[0] == 2 {
343+
if !ufb.union(e[1], e[2]) {
344+
res++
345+
}
346+
}
347+
}
348+
if ufa.n == 1 && ufb.n == 1 {
349+
return res
350+
}
351+
return -1
352+
}
83353
```
84354

85355
### **...**

0 commit comments

Comments
 (0)