【Leetcode】1192. Critical Connections in a Network(代码实现)

206 阅读1分钟

题目地址:

leetcode.com/problems/cr…

代码如下

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {
    public List<List<Integer>> criticalConnections(int n, List<List<Integer>> connections) {
        List<List<Integer>> res = new ArrayList<>();
        
        List<List<Integer>> graph = buildGraph(connections, n);
        int[] ord = new int[n], low = new int[n];
        boolean[] visited = new boolean[n];
        
        for (int i = 0; i < n; i++) {
        	// 找到一个还没访问过的连通分量
            if (!visited[i]) {
            	// 将时间戳0传进去
                dfs(i, i, 0, ord, low, graph, visited, res);
            }
        }
        
        return res;
    }
    
    // cur是当前遍历的点,parent是cur上一层递归遍历的点,cnt表示访问cur的时间戳(从0开始计数),
    // ord记录每个顶点被访问的时间戳,low记录每个顶点能到达的时间戳最小的点的时间戳(这里的到达指的是非回头路的那种到达)
    private void dfs(int cur, int parent, int cnt, int[] ord, int[] low, List<List<Integer>> graph, boolean[] visited, List<List<Integer>> res) {
    	// 标记当前顶点为已访问
        visited[cur] = true;
        // 先初始化cur的ord和low为当前访问的时间戳
        ord[cur] = cnt;
        low[cur] = cnt;
        
        // 遍历cur的邻接点
        for (int next : graph.get(cur)) {
        	// 对cur的邻接点进行算法逻辑。
        	// 如果未访问,则对其进行访问,回溯的时候看一下cur与next的边是否是桥,并更新low[cur];
        	// 如果不是parent但是已经访问,则直接更新low[cur];
        	// 如果是parent那直接略过
            if (!visited[next]) {
            	// 将时间戳加上1传递到下一层递归里去
                dfs(next, cur, cnt + 1, ord, low, graph, visited, res);
                
                // 发现了桥,加进答案中
                if (low[next] > ord[cur]) {
                    res.add(Arrays.asList(cur, next));
                }
                
                // 回溯之前要用low[next]来更新low[cur]
                low[cur] = Math.min(low[cur], low[next]);
            } else if (next != parent) {
            	// 如果next已经被访问过,但不是parent,那么cur就有可能从另一条路到达时间戳更早的点,更新low[cur]
                low[cur] = Math.min(low[cur], low[next]);
            }
        }
    }
    
    // 邻接表建图
    private List<List<Integer>> buildGraph(List<List<Integer>> connections, int n) {
        List<List<Integer>> graph = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            graph.add(new ArrayList<>());
        }
        
        for (List<Integer> connection : connections) {
            int u = connection.get(0), v = connection.get(1);
            graph.get(u).add(v);
            graph.get(v).add(u);
        }
        
        return graph;
    }
}