Рубрики
Без рубрики

Решение: Критические соединения в сети

Это является частью серии пояснений решения LeetCode (индекс). Если вам понравилось это решение или Фу … помечены алгоритмами, JavaScript, Java, Python.

Это является частью серии объяснений решения 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”