JAVA程序设计:查找集群内的「关键连接」(LeetCode:1192)

力扣数据中心有 n 台服务器,分别按从 0 到 n-1 的方式进行了编号。

它们之间以「服务器到服务器」点对点的形式相互连接组成了一个内部集群,其中连接 connections 是无向的。

从形式上讲,connections[i] = [a, b] 表示服务器 a 和 b 之间形成连接。任何服务器都可以直接或者间接地通过网络到达任何其他服务器。

「关键连接」是在该集群中的重要连接,也就是说,假如我们将它移除,便会导致某些服务器无法访问其他服务器。

请你以任意顺序返回该集群内的所有 「关键连接」。

 

示例 1:

输入:n = 4, connections = [[0,1],[1,2],[2,0],[1,3]]
输出:[[1,3]]
解释:[[3,1]] 也是正确的。
 

提示:

1 <= n <= 10^5
n-1 <= connections.length <= 10^5
connections[i][0] != connections[i][1]
不存在重复的连接

思路:强连通分量模板题,不懂强连通的可以戳这里,假设你已经掌握了强连通分量算法,从题目中不难看出,我们要找的就是无向连通图中的桥。

class Solution {

    private int t;
    private int[] dfn, low;
    private boolean[] vis;
    private List[] edges;
    private List> ans;


    public List> criticalConnections(int n, List> connections) {

        t = 0;
        this.dfn = new int[n];
        this.low = new int[n];
        this.vis = new boolean[n];
        this.ans = new ArrayList<>();
        this.edges = new ArrayList[n];

        for (int i = 0; i < n; i++)
            edges[i] = new ArrayList<>();

        for (List cur : connections) {
            int u = cur.get(0), v = cur.get(1);
            edges[u].add(v);
            edges[v].add(u);
        }

        tarjan(0, -1);

        return ans;

    }

    private void tarjan(int u, int pre) {

        vis[u] = true;
        dfn[u] = low[u] = ++t;
        for (int v : edges[u]) {
            if (v == pre) continue;
            if (!vis[v]) {
                tarjan(v, u);
                low[u] = Math.min(low[u], low[v]);
                if (low[v] > dfn[u]) {
                    List tmp = new ArrayList<>();
                    tmp.add(u);
                    tmp.add(v);
                    ans.add(new ArrayList<>(tmp));
                }
            }
            else
                low[u] = Math.min(low[u], dfn[v]);
        }
    }
}

 

你可能感兴趣的:(JAVA程序设计:查找集群内的「关键连接」(LeetCode:1192))