力扣数据中心有 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<Integer>[] edges;
private List<List<Integer>> ans;
public List<List<Integer>> criticalConnections(int n, List<List<Integer>> 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<Integer> 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<Integer> tmp = new ArrayList<>();
tmp.add(u);
tmp.add(v);
ans.add(new ArrayList<>(tmp));
}
}
else
low[u] = Math.min(low[u], dfn[v]);
}
}
}