Это является частью серии объяснений решения LeetCode ( index ). Если вам понравилось это решение или нашел его полезным, Пожалуйста, как Этот пост и/или УПОТАТЬ Мое решение пост на форумах LeetCode Отказ
Проблема летета # 1192 (HARD): Критические соединения в сети
Описание:
( Перейти к : Идея решения Код : JavaScript | Python |. Java |. C ++
Есть n серверов, пронумерованные из 0
к N-1
Соединенные неращими подключенными серверами к серверу, образующие сеть, где соединения [I] = [а, б]
представляет связь между серверами А
и B
Отказ Любой сервер может достигать любого другого сервера прямо или косвенно через сеть.
А Критическое соединение Это соединение, которое, если удалить, сделает какой-нибудь сервер не может достичь какого-либо другого сервера.
Верните все критические соединения в сети в любом порядке.
Примеры:
Вход: | |
Выход: | [[1,3]] |
Объяснение: | [[3,1]] также принимается. |
Визуальный |
Ограничения:
1^5
N-1.Length ^ 5
Соединения [I] [0] [I] [1]
- Нет повторных подключений.
Идея:
( Перейти к : Описание проблемы Код : JavaScript | Python |. Java |. C ++
Если мы будем думать о сети и ее соединениях, таких как неопрященный график и его края, то критическое соединение, как определено этой проблемой, совпадает с мостом на графике. Чтобы узнать, какие кромки являются мостами, мы можем использовать Алгоритм моста Тайджана ( TBFA ).
TBFA немного похоже на комбинацию Глубинный поиск ( DFS ) Подход с Рекурсия и а Союз найди Отказ В TBFA мы делаем рекурсивные DF на нашем графике и для каждого узла, мы отслеживаем самый ранний узел, который мы можем обручиться до достижения. Делая это, мы можем определить, является ли данный край мостом, потому что дальний узел не ведет к любому другому более раннему узлу.
Для реализации нашей TBFA первое, что мы должны сделать, это построить краевая карта ( edgemap ) от Соединения список. Каждый ключ на нашей краевой карте должен соответствовать определенному узлу, и его значение должно быть массивом каждого соседнего узла к клавишему узлу.
Нам также понадобится отдельные массивы для хранения времени обнаружения ( Disc ) и самый низкий будущий узл ( Low ) для каждого узла, а также время счетчик использовать с Диск Отказ
Для нашего рекурсивного помощника DFS ( DFS ) каждый недавно посещаемый узел должен установить свое начальное значение для обоих Диск и Низкий к текущей стоимости время до время увеличивается. ( Примечание: если мы начнем Время в 1 вместо 0 , Мы можем использовать либо дисковый или Низкий в качестве посещаемого массива, а не должен держать отдельный массив для этой цели. Любое ненулевое значение в выбранном массиве будет затем представляет посещенное состояние для данного узла. )
Тогда мы рекурсивно звоните DFS На каждом из невизимых соседних узлов ( Next ) текущего узла ( Curry ). Если один из возможных Следующий Узлы – более ранний узел ( Диск [Далее]
Если после отступления, значение Низкий [Далее] все еще выше, чем Низкая [CUR] , то нет петли соединения, что означает, что край между Curry и Следующий Это мост, поэтому мы должны добавить его на наш артикул ответа ( ANS ).
Однажды DFS Функция HELPER завершила свой обход, мы можем Вернуть АНС Отказ
Реализация:
JavaScript странно работает значительно быстрее с регулярным объектом, а не на карте ().
Код JavaScript:
( Перейти к : Описание проблемы Идея решения
var criticalConnections = function(n, connections) { let edgeMap = {} for (let i = 0; i < n; i++) edgeMap[i] = [] for (let [a,b] of connections) edgeMap[a].push(b), edgeMap[b].push(a) let disc = new Uint32Array(n), low = new Uint32Array(n), time = 1, ans = [] const dfs = (curr, prev) => { disc[curr] = low[curr] = time++ for (let next of edgeMap[curr]) { if (!disc[next]) { dfs(next, curr) low[curr] = Math.min(low[curr], low[next]) } else if (next !== prev) low[curr] = Math.min(low[curr], disc[next]) if (low[next] > disc[curr]) ans.push([curr, next]) } } dfs(0, -1) return ans };
Код Python:
( Перейти к : Описание проблемы Идея решения
class Solution: def criticalConnections(self, n: int, connections: List[List[int]]) -> List[List[int]]: edgeMap = defaultdict(list) for a,b in connections: edgeMap[a].append(b) edgeMap[b].append(a) disc, low, time, ans = [0] * n, [0] * n, [1], [] def dfs(curr: int, prev: int): disc[curr] = low[curr] = time[0] time[0] += 1 for next in edgeMap[curr]: if not disc[next]: dfs(next, curr) low[curr] = min(low[curr], low[next]) elif next != prev: low[curr] = min(low[curr], disc[next]) if low[next] > disc[curr]: ans.append([curr, next]) dfs(0, -1) return ans
Java код:
( Перейти к : Описание проблемы Идея решения
class Solution { int[] disc, low; int time = 1; List> ans = new ArrayList<>(); Map
> edgeMap = new HashMap<>(); public List > criticalConnections(int n, List
> connections) { disc = new int[n]; low = new int[n]; for (int i = 0; i < n; i++) edgeMap.put(i, new ArrayList
()); for (List conn : connections) { edgeMap.get(conn.get(0)).add(conn.get(1)); edgeMap.get(conn.get(1)).add(conn.get(0)); } dfs(0, -1); return ans; } public void dfs(int curr, int prev) { disc[curr] = low[curr] = time++; for (int next : edgeMap.get(curr)) { if (disc[next] == 0) { dfs(next, curr); low[curr] = Math.min(low[curr], low[next]); } else if (next != prev) low[curr] = Math.min(low[curr], disc[next]); if (low[next] > disc[curr]) ans.add(Arrays.asList(curr, next)); } } }
C ++ код:
( Перейти к : Описание проблемы Идея решения
class Solution { public: vector> criticalConnections(int n, vector >& connections) { disc = vector (n); low = vector (n); for (auto conn : connections) { edgeMap[conn[0]].push_back(conn[1]); edgeMap[conn[1]].push_back(conn[0]); } dfs(0, -1); return ans; } void dfs(int curr, int prev) { disc[curr] = low[curr] = time++; for (int next : edgeMap[curr]) { if (disc[next] == 0) { dfs(next, curr); low[curr] = min(low[curr], low[next]); } else if (next != prev) low[curr] = min(low[curr], disc[next]); if (low[next] > disc[curr]) ans.push_back({curr, next}); } } private: vector disc{0}, low{0}; int time = 1; vector > ans; unordered_map > edgeMap; };
Оригинал: “https://dev.to/seanpgallivan/solution-critical-connections-in-a-network-51g0”