Skip to content

Commit dcfb5c2

Browse files
committed
feat: add solutions to lc problem: No.1489
No.1489.Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree
1 parent 5d88a1a commit dcfb5c2

File tree

17 files changed

+861
-17
lines changed

17 files changed

+861
-17
lines changed

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,9 @@
115115

116116
- [网络延迟时间](/solution/0700-0799/0743.Network%20Delay%20Time/README.md) - 最短路、Dijkstra 算法、Bellman Ford 算法、SPFA 算法
117117
- [连接所有点的最小费用](/solution/1500-1599/1584.Min%20Cost%20to%20Connect%20All%20Points/README.md) - 最小生成树、Prim 算法、Kruskal 算法
118-
- [最低成本联通所有城市](/solution/1100-1199/1135.Connecting%20Cities%20With%20Minimum%20Cost/README.md) - 最小生成树、Kruskal 算法
119-
- [水资源分配优化](/solution/1100-1199/1168.Optimize%20Water%20Distribution%20in%20a%20Village/README.md) - 最小生成树、Kruskal 算法
118+
- [最低成本联通所有城市](/solution/1100-1199/1135.Connecting%20Cities%20With%20Minimum%20Cost/README.md) - 最小生成树、Kruskal 算法、并查集
119+
- [水资源分配优化](/solution/1100-1199/1168.Optimize%20Water%20Distribution%20in%20a%20Village/README.md) - 最小生成树、Kruskal 算法、并查集
120+
- [找到最小生成树里的关键边和伪关键边](/solution/1400-1499/1489.Find%20Critical%20and%20Pseudo-Critical%20Edges%20in%20Minimum%20Spanning%20Tree/README.md) - 最小生成树、Kruskal 算法、并查集
120121

121122
<!-- 待补充
122123
### 6. 数学知识

README_EN.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,10 @@ Complete solutions to [LeetCode](https://leetcode.com/problemset/all/), [LCOF](h
110110
### 5. Graph Theory
111111

112112
- [Network Delay Time](/solution/0700-0799/0743.Network%20Delay%20Time/README_EN.md) - Shortest Path, Dijkstra's algorithm, Bellman Ford's algorithm, SPFA
113-
- [Min Cost to Connect All Points](/solution/1500-1599/1584.Min%20Cost%20to%20Connect%20All%20Points/README_EN.md) - Minimum Spanning Tree, Prim's algorithm, Kruskal's algorithm
113+
- [Min Cost to Connect All Points](/solution/1500-1599/1584.Min%20Cost%20to%20Connect%20All%20Points/README_EN.md) - Minimum Spanning Tree, Prim's algorithm, Kruskal's algorithm, Union find
114114
- [Connecting Cities With Minimum Cost](/solution/1100-1199/1135.Connecting%20Cities%20With%20Minimum%20Cost/README_EN.md) - Minimum Spanning Tree, Kruskal's algorithm
115-
- [Optimize Water Distribution in a Village](/solution/1100-1199/1168.Optimize%20Water%20Distribution%20in%20a%20Village/README_EN.md) - Minimum Spanning Tree, Kruskal's algorithm
115+
- [Optimize Water Distribution in a Village](/solution/1100-1199/1168.Optimize%20Water%20Distribution%20in%20a%20Village/README_EN.md) - Minimum Spanning Tree, Kruskal's algorithm, Union find
116+
- [Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree](/solution/1400-1499/1489.Find%20Critical%20and%20Pseudo-Critical%20Edges%20in%20Minimum%20Spanning%20Tree/README_EN.md) - Minimum Spanning Tree, Kruskal's algorithm, Union find
116117

117118
<!--
118119
### 6. Mathematical Knowledge

solution/0700-0799/0706.Design HashMap/Solution.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
class MyHashMap:
2-
32
def __init__(self):
43
self.data = [-1] * 1000001
54

solution/0700-0799/0743.Network Delay Time/Solution.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
class Solution:
22
def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
3-
INF = 0x3f3f
3+
INF = 0x3F3F
44
g = defaultdict(list)
55
for u, v, w in times:
66
g[u - 1].append((v - 1, w))

solution/0700-0799/0787.Cheapest Flights Within K Stops/Solution.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
class Solution:
2-
def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:
3-
INF = 0x3f3f3f3f
2+
def findCheapestPrice(
3+
self, n: int, flights: List[List[int]], src: int, dst: int, k: int
4+
) -> int:
5+
INF = 0x3F3F3F3F
46
dist = [INF] * n
57
dist[src] = 0
68
for _ in range(k + 1):

solution/1100-1199/1129.Shortest Path with Alternating Colors/Solution.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
class Solution:
2-
def shortestAlternatingPaths(self, n: int, redEdges: List[List[int]], blueEdges: List[List[int]]) -> List[int]:
2+
def shortestAlternatingPaths(
3+
self, n: int, redEdges: List[List[int]], blueEdges: List[List[int]]
4+
) -> List[int]:
35
red = defaultdict(list)
46
blue = defaultdict(list)
57
for i, j in redEdges:

solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
class Solution:
2-
def maxCandies(self, status: List[int], candies: List[int], keys: List[List[int]], containedBoxes: List[List[int]], initialBoxes: List[int]) -> int:
2+
def maxCandies(
3+
self,
4+
status: List[int],
5+
candies: List[int],
6+
keys: List[List[int]],
7+
containedBoxes: List[List[int]],
8+
initialBoxes: List[int],
9+
) -> int:
310
q = deque([i for i in initialBoxes if status[i] == 1])
411
ans = sum(candies[i] for i in initialBoxes if status[i] == 1)
512
has = set(initialBoxes)

solution/1400-1499/1489.Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree/README.md

+279
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,301 @@
5353

5454
<!-- 这里可写通用的实现逻辑 -->
5555

56+
最小生成树问题。
57+
58+
- 关键边:若删去某条边,导致整个图不连通,或者最小生成树的权值变大,那么这条边就是关键边。
59+
- 伪关键边:对于非关键边,我们尝试将该边加入最小生成树集合中,若最小生成树的权值不变,那么这条边就是非关键边。
60+
61+
**方法一:Kruskal 算法**
62+
63+
先利用 Kruskal 算法,得出最小生成树的权值 v。然后依次枚举每条边,按上面的方法,判断是否是关键边;如果不是关键边,再判断是否是伪关键边。
64+
5665
<!-- tabs:start -->
5766

5867
### **Python3**
5968

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

6271
```python
72+
class UnionFind:
73+
def __init__(self, n):
74+
self.p = list(range(n))
75+
self.n = n
76+
77+
def union(self, a, b):
78+
if self.find(a) == self.find(b):
79+
return False
80+
self.p[self.find(a)] = self.find(b)
81+
self.n -= 1
82+
return True
83+
84+
def find(self, x):
85+
if self.p[x] != x:
86+
self.p[x] = self.find(self.p[x])
87+
return self.p[x]
88+
6389

90+
class Solution:
91+
def findCriticalAndPseudoCriticalEdges(self, n: int, edges: List[List[int]]) -> List[List[int]]:
92+
for i, e in enumerate(edges):
93+
e.append(i)
94+
edges.sort(key=lambda x: x[2])
95+
uf = UnionFind(n)
96+
v = sum(w for f, t, w, _ in edges if uf.union(f, t))
97+
ans = [[], []]
98+
for f, t, w, i in edges:
99+
uf = UnionFind(n)
100+
k = sum(z for x, y, z, j in edges if j != i and uf.union(x, y))
101+
if uf.n > 1 or (uf.n == 1 and k > v):
102+
ans[0].append(i)
103+
continue
104+
105+
uf = UnionFind(n)
106+
uf.union(f, t)
107+
k = w + sum(z for x, y, z, j in edges if j != i and uf.union(x, y))
108+
if k == v:
109+
ans[1].append(i)
110+
return ans
64111
```
65112

66113
### **Java**
67114

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

70117
```java
118+
class Solution {
119+
public List<List<Integer>> findCriticalAndPseudoCriticalEdges(int n, int[][] edges) {
120+
for (int i = 0; i < edges.length; ++i) {
121+
int[] e = edges[i];
122+
int[] t = new int[4];
123+
System.arraycopy(e, 0, t, 0, 3);
124+
t[3] = i;
125+
edges[i] = t;
126+
}
127+
Arrays.sort(edges, Comparator.comparingInt(a -> a[2]));
128+
int v = 0;
129+
UnionFind uf = new UnionFind(n);
130+
for (int[] e : edges) {
131+
int f = e[0], t = e[1], w = e[2];
132+
if (uf.union(f, t)) {
133+
v += w;
134+
}
135+
}
136+
List<List<Integer>> ans = new ArrayList<>();
137+
for (int i = 0; i < 2; ++i) {
138+
ans.add(new ArrayList<>());
139+
}
140+
for (int[] e : edges) {
141+
int f = e[0], t = e[1], w = e[2], i = e[3];
142+
uf = new UnionFind(n);
143+
int k = 0;
144+
for (int[] ne : edges) {
145+
int x = ne[0], y = ne[1], z = ne[2], j = ne[3];
146+
if (j != i && uf.union(x, y)) {
147+
k += z;
148+
}
149+
}
150+
if (uf.getN() > 1 || (uf.getN() == 1 && k > v)) {
151+
ans.get(0).add(i);
152+
continue;
153+
}
154+
uf = new UnionFind(n);
155+
uf.union(f, t);
156+
k = w;
157+
for (int[] ne : edges) {
158+
int x = ne[0], y = ne[1], z = ne[2], j = ne[3];
159+
if (j != i && uf.union(x, y)) {
160+
k += z;
161+
}
162+
}
163+
if (k == v) {
164+
ans.get(1).add(i);
165+
}
166+
}
167+
return ans;
168+
}
169+
}
170+
171+
class UnionFind {
172+
private int[] p;
173+
private int n;
174+
175+
public UnionFind(int n) {
176+
p = new int[n];
177+
this.n = n;
178+
for (int i = 0; i < n; ++i) {
179+
p[i] = i;
180+
}
181+
}
182+
183+
public int getN() {
184+
return n;
185+
}
186+
187+
public boolean union(int a, int b) {
188+
if (find(a) == find(b)) {
189+
return false;
190+
}
191+
p[find(a)] = find(b);
192+
--n;
193+
return true;
194+
}
195+
196+
public int find(int x) {
197+
if (p[x] != x) {
198+
p[x] = find(p[x]);
199+
}
200+
return p[x];
201+
}
202+
}
203+
```
204+
205+
### **C++**
206+
207+
```cpp
208+
class UnionFind {
209+
public:
210+
vector<int> p;
211+
int n;
212+
213+
UnionFind(int _n): n(_n), p(_n) {
214+
iota(p.begin(), p.end(), 0);
215+
}
216+
217+
bool unite(int a, int b) {
218+
if (find(a) == find(b)) return false;
219+
p[find(a)] = find(b);
220+
--n;
221+
return true;
222+
}
223+
224+
int find(int x) {
225+
if (p[x] != x) p[x] = find(p[x]);
226+
return p[x];
227+
}
228+
};
229+
230+
class Solution {
231+
public:
232+
vector<vector<int>> findCriticalAndPseudoCriticalEdges(int n, vector<vector<int>>& edges) {
233+
for (int i = 0; i < edges.size(); ++i) edges[i].push_back(i);
234+
sort(edges.begin(), edges.end(), [](auto& a, auto& b) {return a[2] < b[2];});
235+
int v = 0;
236+
UnionFind uf(n);
237+
for (auto& e : edges)
238+
{
239+
int f = e[0], t = e[1], w = e[2];
240+
if (uf.unite(f, t)) v += w;
241+
}
242+
vector<vector<int>> ans(2);
243+
for (auto& e : edges)
244+
{
245+
int f = e[0], t = e[1], w = e[2], i = e[3];
246+
UnionFind ufa(n);
247+
int k = 0;
248+
for (auto& ne : edges)
249+
{
250+
int x = ne[0], y = ne[1], z = ne[2], j = ne[3];
251+
if (j != i && ufa.unite(x, y)) k += z;
252+
}
253+
if (ufa.n > 1 || (ufa.n == 1 && k > v))
254+
{
255+
ans[0].push_back(i);
256+
continue;
257+
}
258+
259+
UnionFind ufb(n);
260+
ufb.unite(f, t);
261+
k = w;
262+
for (auto& ne : edges)
263+
{
264+
int x = ne[0], y = ne[1], z = ne[2], j = ne[3];
265+
if (j != i && ufb.unite(x, y)) k += z;
266+
}
267+
if (k == v) ans[1].push_back(i);
268+
}
269+
return ans;
270+
}
271+
};
272+
```
273+
274+
### **Go**
275+
276+
```go
277+
type unionFind struct {
278+
p []int
279+
n int
280+
}
281+
282+
func newUnionFind(n int) *unionFind {
283+
p := make([]int, n)
284+
for i := range p {
285+
p[i] = i
286+
}
287+
return &unionFind{p, n}
288+
}
289+
290+
func (uf *unionFind) find(x int) int {
291+
if uf.p[x] != x {
292+
uf.p[x] = uf.find(uf.p[x])
293+
}
294+
return uf.p[x]
295+
}
296+
297+
func (uf *unionFind) union(a, b int) bool {
298+
if uf.find(a) == uf.find(b) {
299+
return false
300+
}
301+
uf.p[uf.find(a)] = uf.find(b)
302+
uf.n--
303+
return true
304+
}
71305
306+
func findCriticalAndPseudoCriticalEdges(n int, edges [][]int) [][]int {
307+
for i := range edges {
308+
edges[i] = append(edges[i], i)
309+
}
310+
sort.Slice(edges, func(i, j int) bool {
311+
return edges[i][2] < edges[j][2]
312+
})
313+
v := 0
314+
uf := newUnionFind(n)
315+
for _, e := range edges {
316+
f, t, w := e[0], e[1], e[2]
317+
if uf.union(f, t) {
318+
v += w
319+
}
320+
}
321+
ans := make([][]int, 2)
322+
for _, e := range edges {
323+
f, t, w, i := e[0], e[1], e[2], e[3]
324+
uf = newUnionFind(n)
325+
k := 0
326+
for _, ne := range edges {
327+
x, y, z, j := ne[0], ne[1], ne[2], ne[3]
328+
if j != i && uf.union(x, y) {
329+
k += z
330+
}
331+
}
332+
if uf.n > 1 || (uf.n == 1 && k > v) {
333+
ans[0] = append(ans[0], i)
334+
continue
335+
}
336+
uf = newUnionFind(n)
337+
uf.union(f, t)
338+
k = w
339+
for _, ne := range edges {
340+
x, y, z, j := ne[0], ne[1], ne[2], ne[3]
341+
if j != i && uf.union(x, y) {
342+
k += z
343+
}
344+
}
345+
if k == v {
346+
ans[1] = append(ans[1], i)
347+
}
348+
}
349+
return ans
350+
}
72351
```
73352

74353
### **...**

0 commit comments

Comments
 (0)