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<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]);
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值