Нахождение корня дерева

Как из набора узлов и ребер получить дерево с корнем? (Я работаю с матрицей связности, каждое ребро имеет вес: graph[i][j], без отрицательных ребер). Позже мне нужно сделать DFS и найти LCA в этом дереве, так что это было бы хорошо для оптимизации.


person sashab    schedule 05.08.2011    source источник
comment
Я так понимаю, это ориентированный граф? В противном случае любой узел в дереве был бы действительным корнем.   -  person hammar    schedule 06.08.2011
comment
Да, график направленный, задача сменить ориентацию(?)   -  person sashab    schedule 06.08.2011


Ответы (4)


Я предполагаю, что ваша матрица представляет дочерние отношения (т. е. M[i][j] говорит, что j является дочерним элементом i), для направленного граф G(V,E).

У вас есть 2 разные стратегии:

  • используйте битовый вектор, просмотрите каждую ячейку вашей матрицы и отметьте дочерний индекс в векторе, если вес ячейки не равен нулю): корень - это вершина, не заданная в векторе,
  • найдите столбцы (или строки, если ваша матрица является столбцом первым), чьи ячейки все нулевые (без предков),

Второе решение лучше подходит для плотных матриц. Его худшее время работы будет, когда корень является последней записью (O (V²)). В этом случае вы можете остановиться при первом попадании или бежать до конца, чтобы собрать все корни, если в вашем графе их много.

Первый лучше подходит для разреженных матриц, так как нужно пройтись по всем ячейкам. Его время работы составляет O (E). Вы также получаете все корни с этим алгоритмом.

Если вы уверены, что ваш граф имеет только один корень, вы можете использовать технику обхода ребер, как описано в других ответах.

person didierc    schedule 19.11.2012

Выберите один узел в дереве и идите вверх, то есть против ориентации ребер. Когда вы найдете узел без предка, у вас есть корень.

Если вам нужно делать что-то подобное часто, просто запомните родительский узел для каждого узла.

person svick    schedule 05.08.2011
comment
Я не уверен, что граф ОП - это дерево, я думаю, что у него есть граф, и ему нужно найти остовное дерево. Например, в клике алгоритм никогда не завершится (или не завершится, если вы сохраните набор посещенных узлов), но в нем определенно есть остовное дерево. - person amit; 06.08.2011
comment
Вопрос о «нахождении корня дерева», вот на что я отвечал. Очевидно, что если у ОП нет дерева, то он должен указать, что у него есть и что именно он хочет найти. - person svick; 06.08.2011
comment
Решение для меня было: сделать симметричную матрицу связности, сделать DFS для любого узла (узел 0, например), тогда все работает нормально. - person sashab; 06.08.2011

Вот ГОРАЗДО МЕДЛЕННАЯ в вычислительном отношении версия, которую также намного проще кодировать. Для небольших графиков это нормально.

Найдите узел с нулевой степенью входа!

Вы должны вычислить степени всех узлов, O(n), но в зависимости от настройки это часто намного проще закодировать и, следовательно, менее подвержено ошибкам.

person karl    schedule 31.08.2017

поиск в глубину из любого графа дает вам дерево (конечно, при условии, что граф связан).

вы можете повторить его и начать с каждого узла в качестве возможного корня, в конечном итоге вы получите остовное дерево, если оно есть. сложность будет O(V^2+VE)

EDIT: это работает, потому что для любого конечного графа, если есть узел корневой формы от a до узла b, в дереве, создаваемом DFS, будет путь от a до b. Итак, если предположить, что существует возможное остовное дерево, есть корень r, из которого вы можете перейти к каждому v в V. при итерации, когда r выбрано в качестве корня, существует путь от r к каждому v в V, поэтому будет — путь от r к нему в остовном дереве.

person amit    schedule 05.08.2011
comment
Итак, ситуация: два узла подключены к одному. Граф направлен, выполнение DFS из центрального узла ничего не даст (направленные соединения) - person sashab; 06.08.2011
comment
@scrat: повторите его для каждого узла как возможного корня, вы в конечном итоге найдете допустимое остовное дерево, если оно есть. - person amit; 06.08.2011
comment
@scrat: посмотрите на редактирование, добавлено небольшое объяснение, почему это работает, формальное доказательство должно быть легким, следуя этим рекомендациям (при необходимости). - person amit; 06.08.2011
comment
Но для этого мне понадобится симметричная матрица связности? Примерный список узлов-источников, узлов-назначений и весов границ: pastebin.com/cQP9PEpm Корня просто нет ! - person sashab; 06.08.2011
comment
Я вас наверное неправильно понял, почему (1) не рут? есть путь 1->2,2->3, поэтому (1) является корнем, есть путь (1->2) до (2) и путь (1->2->3) до (3 ) в связующем дереве DFS. и вам не понадобится симметричная матрица связности, каждое ребро, которого нет в списке, может неявно не существовать. - person amit; 06.08.2011
comment
это не матрица, это список (исходный узел, целевой узел, вес) - person sashab; 06.08.2011