力扣數據中心有 n 臺服務器,分別按從 0 到 n-1 的方式進行了編號。
它們之間以「服務器到服務器」點對點的形式相互連接組成了一個內部集羣,其中連接 connections 是無向的。
從形式上講,connections[i] = [a, b] 表示服務器 a 和 b 之間形成連接。任何服務器都可以直接或者間接地通過網絡到達任何其他服務器。
「關鍵連接」是在該集羣中的重要連接,也就是說,假如我們將它移除,便會導致某些服務器無法訪問其他服務器。
請你以任意順序返回該集羣內的所有 「關鍵連接」。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/critical-connections-in-a-network
輸入:n = 4, connections = [[0,1],[1,2],[2,0],[1,3]]
輸出:[[1,3]]
解釋:[[3,1]] 也是正確的。
提示
不存在重複的連接
題解
顯然這是一個圖,但是如果要找到關鍵的連接,主要是要確保這個連接不在一個圓環中,即在一個圓環中,如果去點這個連接也是可以訪問到其他節點的。
我們採用深度搜索的方式,我們可以看看我們是否可以訪問到已經訪問過的節點,對於一個的節點的子節點,可能會訪問到不同的已經訪問過的節點,我們用節點的深度來對訪問的節點進行比較(深度越小,被訪問的時間越早),那麼對於一個節點來說,它能回溯的最高的節點就是深度最小的節點,那麼這個連接就不是關鍵連接。如果一個連接下的所有子節點能回溯的深度都比當前節點大,即不能構成環,那麼這個連接就是關鍵連接。
var ans [][]int
var depth []int
var visit []bool
var recallMinDepth []int
var graph [][]int
func min(a, b int) int {
if a > b {
return b
}
return a
}
func dfs(node int, pre int,dep int) {
visit[node] = true
depth[node] = dep
recallMinDepth[node] = dep
for i:=0;i<len(graph[node]);i++{
if pre == graph[node][i] {
continue
}
if visit[graph[node][i]] == true {
recallMinDepth[node] = min(recallMinDepth[node], depth[graph[node][i]])
continue
}
dfs(graph[node][i], node , dep+1)
recallMinDepth[node] = min(recallMinDepth[node], recallMinDepth[graph[node][i]])
if recallMinDepth[graph[node][i]] > depth[node] {
ans = append(ans, []int{node, graph[node][i]})
}
}
}
func criticalConnections(n int, connections [][]int) [][]int {
ans = make([][]int ,0)
graph = make([][]int, n)
depth = make([]int, n)
visit = make([]bool, n)
recallMinDepth = make([]int, n)
for i:=0;i<n;i++ {
graph[i] = make([]int,0)
}
for i:=0;i<len(connections);i++{
graph[connections[i][0]] = append(graph[connections[i][0]], connections[i][1])
graph[connections[i][1]] = append(graph[connections[i][1]], connections[i][0])
}
dfs(0,-1,1)
return ans
}