Главное меню
Мы солидарны с Украиной. Узнайте здесь, как можно поддержать Украину.

Теория графов

Автор RawonaM, июня 7, 2011, 19:36

0 Пользователи и 1 гость просматривают эту тему.

GaLL

Цитата: RawonaM от ноября 23, 2011, 15:16
In graph theory, a graph is k-edge-connected if it remains connected whenever fewer than k edges are removed.
Треугольник (K3) - двусвязный (2-edge-connected) граф.
Кажется, я решил эту задачу, но доказательство получилось не очень красивое.

RawonaM

Думаю я понял, что значит "k-edge-connected". Это значит, что каждая вершина связана как минимум k-egd-aми со всеми другими вершинами, то есть если убрать к-1 ребер от этой вершины (т.е. оставить только одну), то граф все еще будет связаным.

GaLL

Какое бы разбиение вершин графа на два множества мы ни взяли, будут хотя бы k рёбер, каждое из которых соединяет пару вершин из разных множеств.

RawonaM

Цитата: GaLL от ноября 23, 2011, 15:52
Какое бы разбиение вершин графа на два множества мы ни взяли, будут хотя бы k рёбер, каждое из которых соединяет пару вершин из разных множеств.
Ага, так понятнее, спасибо. Действительно, это получается как бы "k мостов" между двумя компонентами.

RawonaM

Цитата: GaLL от ноября 23, 2011, 15:43
Кажется, я решил эту задачу, но доказательство получилось не очень красивое.
И как вы доказали?
Роббинс в 1939 г доказал через разложение уха. (wiki/en) Ear_decomposition
Ничего проще я не могу придумать.

RawonaM

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

Bhudh

Цитата: RawonaM от Роббинс в 1939 г доказал через разложение уха.
Таким переводом надо рассказ Кинга называть...
Пиши, что думаешь, но думай, что пишешь.
MONEŌ ERGŌ MANEŌ.
Waheeba dokin ʔebi naha.
«каждый пост в интернете имеет коэффициент бреда» © Невский чукчо

RawonaM

Пожалуйста, проследите за логикой, есть ли ошибки:

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

Дан базовый граф G. Запускаем DFS ((wiki/en) Depth-first_search) с любой вершины, допустим с V1.
Если DFS выдал больше, чем одно дерево, ответ отрицательный.
Если одно, то мы получили пути от V1 ко всем листьям дерева.
Убираем с графа G все ребра, которые присутствуют на дереве DFS.
Снова запускаем DFS с вершины V1. Если в результате на одном дереве присуствуют все листья с предыдущего DFS дерева, то мы нашли по два независимых путя* от любой вершины к другой, если нет, то этого невозможно сделать и ответ отрицательный.

*Э-э, не уверен насчет этой формы слова. Может пути?

GaLL

Возьмём граф с вершинами a, b, c, d, e и рёбрами ab, bd, de, ae, bc, cd. Из него легко сделать сильно связный ориентированный, т. к. в нём есть гамильтонов цикл. DFS находит дерево в виде пути abde и ребра cd (конечно, возможны другие деревья DFS'а, это получается, если рассматривать вершины в алфавитном порядке, получится именно такое). Исходный граф минус дерево DFSа - это рёбра ae, bc. c - лист дерева DFSа, но пути до него по оставшимся рёбрам нет.

GaLL

Моё решение:

RawonaM

Ага, понятно.

Мне нужно было алгоритм придумать, который определяет, можно сориентировать граф или нет. Я решил, что с двусвязностью алгоритм получается слишком неэффективный. Вы мой алгоритм не читали или ничего не понятно? :)

GaLL

Цитата: RawonaM от ноября 25, 2011, 14:05
Ага, понятно.

Мне нужно было алгоритм придумать. Я решил, что с двусвязностью алгоритм получается слишком неэффективный. Вы мой алгоритм не читали или ничего не понятно? :)
Читал, но к нему легко подобрать контрпример, см. выше.

RawonaM

Цитата: GaLL от ноября 25, 2011, 14:07
Читал, но к нему легко подобрать контрпример, см. выше.
Действительно. Щас подумаю как надо исправить.

RawonaM

Значит нужно изменить так:

Дан базовый граф G. Запускаем DFS с любой вершины, допустим с V1.
Если DFS выдал больше, чем одно дерево, ответ отрицательный.
Если одно, то даем всем ребрам, которые присутствуют на дереве DFS, ориентацию от листьев к корню, а остальным (добавив их на дерево DFS) наоборот.
Снова запускаем DFS с вершины V1. Если в результате на одном дереве присуствуют все вершины, то мы нашли по два независимых путя* от любой вершины к другой, если нет, то этого невозможно сделать и ответ отрицательный.

Теперь должно работать :)

GaLL

Вы имеете в виду алгоритм проверки графа на возможность сделать из него сильно связный ориентированный? Я думал, вопрос в задаче - каков критерий того, что это можно сделать.
Если же рассматривать вопрос об алгоритме проверки, то, как показано выше, достаточно проверить граф на двусвязность, т. е. связность и отсутствие мостов. Это можно сделать за один DFS. Ваш алгоритм, конечно, тоже работает за O(E), но проверка на мосты с помощью одного DFS'а может быть сделана путём добавления меток только вершинам, а не рёбрам, что требует лишь O(V) дополнительной памяти. :)

RawonaM

Цитата: GaLL от ноября 25, 2011, 14:28
Вы имеете в виду алгоритм проверки графа на возможность сделать из него сильно связный ориентированный? Я думал, вопрос в задаче - каков критерий того, что это можно сделать.
Ну это я его так поставил, хотя изначально нужно было только алгоритм. Потом я подумал, чтобы найти алгоритм  не обязательно знать условие...

Цитата: GaLL от ноября 25, 2011, 14:28
Если же рассматривать вопрос об алгоритме проверки, то, как показано выше, достаточно проверить граф на двусвязность, т. е. связность и отсутствие мостов. Это можно сделать за один DFS. Ваш алгоритм, конечно, тоже работает за O(E), но проверка на мосты с помощью одного DFS'а может быть сделана путём добавления меток только вершинам, а не рёбрам, что требует лишь O(V) дополнительной памяти. :)
А как одним DFS-ом проверить на мосты?
Ну и потом, чтобы идти этим путем нужно сначала доказывать, что действительно такое условие, а это несколько нудное доказательство :)

GaLL

Цитата: RawonaM от ноября 25, 2011, 14:35
А как одним DFS-ом проверить на мосты?
1) В процессе ДФСа каждой вершине присваиваем номер в каком порядке их этот ДФС обходит. Корень - №1, первая попавшаяся вершина, связанная ребром с корнем - №2 и т. д.
2) Кроме того, каждой вершине даём ещё одну метку L - минимальный номер вершины, достигнутой ДФСом из этой вершины (в том числе при обработке обратного ребра; при этом важно не обработать ребро дерева ДФСа как обратное; для этого достаточно в качестве параметра рекурсивной функции ДФСа использовать не только текущую вершину, но и предыдущую).
3) Если в процессе ДФСа мы идём по ребру из вершины a в вершину b по ребру ab (не обратному, т. е. в вершину b при этом попадаем в первый раз), и оказывается, что L[a] < L, то ab - мост.
Цитировать
Ну и потом, чтобы идти этим путем нужно сначала доказывать, что действительно такое условие, а это несколько нудное доказательство :)
Да оно, в общем-то, простое, это я его старался сделать подробнее. :( Частенько простые алгоритмы основываются на довольно длинных доказательствах. Вы видели доказательство верности алгоритма Флойда (длины кратчайших путей между всеми парами вершин графа)?
К тому же, чтобы убедиться в том, что Ваш алгоритм говорит "нет" тогда и только тогда, когда граф не может быть преобразован в сильно связный, нужно всё равно проделать подобное доказательство. :)

RawonaM

Цитата: GaLL от ноября 25, 2011, 14:56
Цитата: RawonaM от ноября 25, 2011, 14:35А как одним DFS-ом проверить на мосты?
1) В процессе ДФСа каждой вершине присваиваем номер в каком порядке их этот ДФС обходит. Корень - №1, первая попавшаяся вершина, связанная ребром с корнем - №2 и т. д.
2) Кроме того, каждой вершине даём ещё одну метку L - минимальный номер вершины, достигнутой ДФСом из этой вершины (в том числе при обработке обратного ребра; при этом важно не обработать ребро дерева ДФСа как обратное; для этого достаточно в качестве параметра рекурсивной функции ДФСа использовать не только текущую вершину, но и предыдущую).
3) Если в процессе ДФСа мы идём по ребру из вершины a в вершину b по ребру ab (не обратному, т. е. в вершину b при этом попадаем в первый раз), и оказывается, что L[a] < L, то ab - мост.
Что-то я не понял, как это происходит. Еще и это доказывать надо будет!


RawonaM

Цитата: GaLL от ноября 25, 2011, 14:56
Частенько простые алгоритмы основываются на довольно длинных доказательствах. Вы видели доказательство верности алгоритма Флойда (длины кратчайших путей между всеми парами вершин графа)?
Неа, не видел.

Цитата: GaLL от ноября 25, 2011, 14:56
К тому же, чтобы убедиться в том, что Ваш алгоритм говорит "нет" тогда и только тогда, когда граф не может быть преобразован в сильно связный, нужно всё равно проделать подобное доказательство. :)
Думаете? Я сначала тоже так думал, потом я вроде как доказал это намного короче.
Вроде как частично я изложил это выше. Щас попробую изложить более внятно.

GaLL

Цитата: RawonaM от ноября 25, 2011, 15:16
Что-то я не понял, как это происходит. Еще и это доказывать надо будет!
Любой алгоритм требует доказательства. Здесь доказательство примерно такое такое же, как для критерия.
Я там ошибся немного, надо не L[a] < L, а num[a] < L, где num - номер вершины, присваеваемый ДФСом. Рекурсию можно сделать, например, так:

// вначале все num и count равны нулю
void DFS(int a, int prev) // a - текущая вершина ДФСа, prev - предыдущая; у корня, то есть при стартовом запуске этой функции, prev равен, например, -1
{
   num[a] = L[a] = ++count;
   for ( b принимает значения всех вершин, соединённых с a ребром )
   {
      if (b == prev)
         continue;
      if (!num)
      {
         // DFS ещё не был в вершине b
         DFS(b, a);
         // теперь значение L установлено и больше меняться не будет
         if (num[a] < L)
            printf("bridge: %d %d\n", a, b);
         if (L[a] > L)   L[a] = L;
      }
      else // обратное ребро
      {
         if (L[a] > num)   L[a] = num;
      }
   }
}

RawonaM

Цитата: GaLL от ноября 25, 2011, 16:20
Цитата: RawonaM от ноября 25, 2011, 15:16Что-то я не понял, как это происходит. Еще и это доказывать надо будет!
Любой алгоритм требует доказательства. Здесь доказательство примерно такое такое же, как для критерия.
В таком случае придется доказывать и критерий и это :) Я пытаюсь сэкономить на писанине и доказательствах. ;D

В книге A first look at graph theory доказательство двусвязности заняло больше страницы мелкого текста.

Меня не покидает ощущение, что эта задача решается гораздо проще. Может я ошибаюсь.

RawonaM

Тут в книге задача, не пойму каким образом она относится к теме.

Допустим дан некий связной граф G. Определим граф H так: вершины будут составлять все остовные деревья графа G, а две вершины T и T' соединены iff они отличаются только одной гранью (т.е. в T' есть одна грань, которой нет в T, и следовательно наоборот). Верно ли, что для любого связного G граф H будет связным?

Мне как-то сразу интуитивно довольно очевидно, что это верно.

Положим, что существует связной граф G, для которого H не связной. Возьмем из H две вершины, T и T', из разных компонент связности. T и T' отличаются n гранями. Без ограничения общности возьмем из T' грань, которой нет в T и добавим ее в T. Теперь в T есть цикл. Удалим из этого цикла ту грань, которой нет в T'. Теперь T и T' отличаются n-1 гранями. Проделываем эту процедуру n раз и получаем, что T и T' находятся в одной компоненте, вопреки тому, что мы их выбирали из разных компонент связности.

Значит такого графа G не существует. Верно?

RawonaM

Нужно предложить алгоритм определения, является ли определенная грань e=(v,w) частью какого-то минимального остовного дерева некоего связанного графа с ве́сами (weights?).

Думаю, что такой граф не существует iff существует путь от v к w, в котором все грани легче е. Для этого убираем все грани тяжелее е и прогоняем BFS или DFS. Если есть путь, то нет минимального дерева с е, если нет пути, то есть такое дерево.

Гораздо непонятнее второй вопрос: какой можно предложить алгоритм определения того, является ли определенная грань e=(v,w) частью всех минимальных остовных деревьев?

По-моему условие такое: грань е является частью всех МОД iff все пути от w к v состоят из граней с весом большим, чем у е (то есть грань е является самой легкой во всех циклах, в которых она состоит) или грань е является мостом.

А вот как это найти, я уже пару дней (с перерывами) пытаюсь понять.
Убирание всех граней тяжелее или легче тут не помогает, нужно придумывать что-то более утонченное.


GaLL

Цитата: RawonaM от декабря 15, 2011, 15:50
Нужно предложить алгоритм определения, является ли определенная грань e=(v,w) частью какого-то минимального остовного дерева некоего связанного графа с ве́сами (weights?).
Находим величину минимального остова данного графа. Потом стягиваем v и w, и у получившегося графа находим величину мин. остова. Если она отличается от предыдущей на вес ребра e, значит, ответ "Да", иначе "Нет".

Быстрый ответ

Обратите внимание: данное сообщение не будет отображаться, пока модератор не одобрит его.

Имя:
Имейл:
Проверка:
Оставьте это поле пустым:
Наберите символы, которые изображены на картинке
Прослушать / Запросить другое изображение

Наберите символы, которые изображены на картинке:

√36:
ALT+S — отправить
ALT+P — предварительный просмотр