Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8be83e8

Browse files
committed
更新并补充了kama0109.冗余链接II的Java版本,附有详细注释
1 parent dc2edca commit 8be83e8

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

‎problems/kamacoder/0109.冗余连接II.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,105 @@ int main() {
250250
## 其他语言版本
251251

252252
### Java
253+
```java
254+
import java.util.ArrayList;
255+
import java.util.List;
256+
import java.util.Scanner;
257+
258+
public class Main {
259+
static int n;
260+
static int[] father = new int[1001]; // 并查集数组
261+
262+
// 并查集初始化
263+
public static void init() {
264+
for (int i = 1; i <= n; ++i) {
265+
father[i] = i;
266+
}
267+
}
268+
269+
// 并查集里寻根的过程
270+
public static int find(int u) {
271+
if (u == father[u]) return u;
272+
return father[u] = find(father[u]); // 路径压缩
273+
}
274+
275+
// 将 v->u 这条边加入并查集
276+
public static void join(int u, int v) {
277+
u = find(u);
278+
v = find(v);
279+
if (u != v) {
280+
father[v] = u; // 合并两棵树
281+
}
282+
}
253283

284+
// 判断 u 和 v 是否有同一个根
285+
public static boolean same(int u, int v) {
286+
return find(u) == find(v);
287+
}
288+
289+
// 在有向图里找到删除的那条边,使其变成树
290+
public static void getRemoveEdge(List<int[]> edges) {
291+
init(); // 初始化并查集
292+
for (int i = 0; i < n; i++) { // 遍历所有的边
293+
if (same(edges.get(i)[0], edges.get(i)[1])) { // 如果构成有向环了,就是要删除的边
294+
System.out.println(edges.get(i)[0] + " " + edges.get(i)[1]);
295+
return;
296+
} else {
297+
join(edges.get(i)[0], edges.get(i)[1]);
298+
}
299+
}
300+
}
301+
302+
// 删一条边之后判断是不是树
303+
public static boolean isTreeAfterRemoveEdge(List<int[]> edges, int deleteEdge) {
304+
init(); // 初始化并查集
305+
for (int i = 0; i < n; i++) {
306+
if (i == deleteEdge) continue;
307+
if (same(edges.get(i)[0], edges.get(i)[1])) { // 如果构成有向环了,一定不是树
308+
return false;
309+
}
310+
join(edges.get(i)[0], edges.get(i)[1]);
311+
}
312+
return true;
313+
}
314+
315+
public static void main(String[] args) {
316+
Scanner sc = new Scanner(System.in);
317+
List<int[]> edges = new ArrayList<>(); // 存储所有的边
318+
319+
n = sc.nextInt(); // 顶点数
320+
int[] inDegree = new int[n + 1]; // 记录每个节点的入度
321+
for (int i = 0; i < n; i++) {
322+
int s = sc.nextInt(); // 边的起点
323+
int t = sc.nextInt(); // 边的终点
324+
inDegree[t]++;
325+
edges.add(new int[]{s, t}); // 将边加入列表
326+
}
327+
328+
List<Integer> vec = new ArrayList<>(); // 记录入度为2的边(如果有的话就两条边)
329+
// 找入度为2的节点所对应的边,注意要倒序,因为优先删除最后出现的一条边
330+
for (int i = n - 1; i >= 0; i--) {
331+
if (inDegree[edges.get(i)[1]] == 2) {
332+
vec.add(i);
333+
}
334+
}
335+
336+
// 情况一、情况二
337+
if (vec.size() > 0) {
338+
// vec里的边已经按照倒叙放的,所以优先删 vec.get(0) 这条边
339+
if (isTreeAfterRemoveEdge(edges, vec.get(0))) {
340+
System.out.println(edges.get(vec.get(0))[0] + " " + edges.get(vec.get(0))[1]);
341+
} else {
342+
System.out.println(edges.get(vec.get(1))[0] + " " + edges.get(vec.get(1))[1]);
343+
}
344+
return;
345+
}
346+
347+
// 处理情况三:明确没有入度为2的情况,一定有有向环,找到构成环的边返回即可
348+
getRemoveEdge(edges);
349+
}
350+
}
351+
```
254352
### Python
255353

256354
### Go

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /