powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Алгоритм определения циклических ссылок
50 сообщений из 50, показаны все 2 страниц
Алгоритм определения циклических ссылок
    #35313377
Farus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35313441
FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.
Ну, скажем, такой алгоритм (типа поиска "в глубину"). Только он очень долгий :)
1. создаем массив вершин графа
2. создаем массив пройденных вершин графа
3. берем первую вершину
4. берем произвольное ребро графа, выходящее из этой вершины.
5. Если вторая вершина ребра графа содержится в массиве пройденных вершин, то мы нашли цикл.
6. В противном случае заносим вершину в пройденные, делаем ее текущей и идем на п.4
7. Если данная вершина является листом (т.е. из нее больше не выходит ребер), то возвращаемся на один уровень вверх (к предыдущей пройденной вершине) и возвращаемся к п.4
8. Если вершин больше не осталось, то мы обошли весь граф.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35313486
Farus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Станислав С...кий FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.
Ну, скажем, такой алгоритм (типа поиска "в глубину"). Только он очень долгий :)
...
5. Если вторая вершина ребра графа содержится в массиве пройденных вершин, то мы нашли цикл.
...

Ну хорошо, эт вроде все будет работать.
А ежели мы накладываем дом условие - граф ориентированный. И тогда понятие цикла несколько меняется.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35313670
Самоловских Виталий aka Kefir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Farus
Ну хорошо, эт вроде все будет работать.
А ежели мы накладываем дом условие - граф ориентированный. И тогда понятие цикла несколько меняется.
А в неориентированном графе две вершины и ребро уже цикл. Алгоритм как раз на ориентированных работает.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35313676
Самоловских Виталий aka Kefir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя нет. В этом случае нужно начинать с каждой вершины и чистить список пройденных. Наверное есть лучший алгоритм, надо книжки читать.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35313930
Гость_0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.хотите написать свою реализацию Spanning Tree алгоритма ? :)
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35314019
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.
Хочу тебя огорчить. Практически 100% алгорутмов теории графов уже были предложены в прошлом веке. Тебе остаётся только почитать теорию и выбрать алгоритм, который наиболее близко подходит к решению твоей задачи.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35314033
Alexsalog
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.
Хочу тебя огорчить. Практически 100% алгорутмов теории графов уже были предложены в прошлом веке. Тебе остаётся только почитать теорию и выбрать алгоритм, который наиболее близко подходит к решению твоей задачи.

Ну я искал по гуглу. Готового не нашел. Хотя алгорим то вообщем то должен быть фундаментальным. :-)
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35314107
Alexsalog
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гость_0 FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.хотите написать свою реализацию Spanning Tree алгоритма ? :)

Это вроде коммуникации. Нее... мне для прикладной программки.
Хотя можно сделать и перебором тупым.... Только боюсь количество переборов будет возрастать в геометрической прогрессии.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35314476
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.
Зависит от того, что именно Вам нужно. Найти все циклы во всех вариантах? Найти фундаментальные циклы? Определить факт наличия циклов без поиска самих циклов? Еще что-нибудь?

И таки да, гугль содержит более чем достаточно информации на эту тему.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35315012
Фотография Lelikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexsalog mayton FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.
Хочу тебя огорчить. Практически 100% алгорутмов теории графов уже были предложены в прошлом веке. Тебе остаётся только почитать теорию и выбрать алгоритм, который наиболее близко подходит к решению твоей задачи.

Ну я искал по гуглу. Готового не нашел. Хотя алгорим то вообщем то должен быть фундаментальным. :-)

Постройте по вашему графу остов. Все ребра, не вошедшие в остов - уже элементы циклов.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35315279
ретти
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
очень интересно, но неоднозначно
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35316451
Alexsalog
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.
Зависит от того, что именно Вам нужно. Найти все циклы во всех вариантах? Найти фундаментальные циклы? Определить факт наличия циклов без поиска самих циклов? Еще что-нибудь?

И таки да, гугль содержит более чем достаточно информации на эту тему.

Найти любые циклы, притом если граф строится итеративно - то сообщить об этом цикле и показать его в момент добавления решающего ребра.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35316483
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тогда есть совершенно очевидный алгоритм. Поддерживать список возможных путей между вершинами графа. То есть начать с одной вершины; далее добавили вершину - ничего не делаем, добавили ребро - достраиваем список путей, используя начинающиеся и заканчивающиеся в вершинах этого ребра. Каждый раз, когда при добавлении ребра АБ уже имеем путь БА или - внимание - несколько таких путей, вот вам, бабушка, и циклы.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35316523
Alexsalog
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarerТогда есть совершенно очевидный алгоритм. Поддерживать список возможных путей между вершинами графа. То есть начать с одной вершины; далее добавили вершину - ничего не делаем, добавили ребро - достраиваем список путей, используя начинающиеся и заканчивающиеся в вершинах этого ребра. Каждый раз, когда при добавлении ребра АБ уже имеем путь БА или - внимание - несколько таких путей, вот вам, бабушка, и циклы.

Получится дикое количество комбинаций......
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35316559
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexsalogПолучится дикое количество комбинаций......
Это если ребра добавляются интерактивно-то? Не очень верится, раньше оператор устанет :)

А так - задача поиска всех циклов, если не ошибаюсь, np-полна, следовательно либо дикое количество комбинаций в памяти, либо перебор того же дикого количества комбинаций на ходу. Можно применять методы сокращения, скажем, железнодорожники строят граф только по узловым станциям (грубо говоря, по развилкам), сжимая вершины один вход - один выход.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35316691
Alexsalog
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer AlexsalogПолучится дикое количество комбинаций......
Это если ребра добавляются интерактивно-то? Не очень верится, раньше оператор устанет :)

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

Насчет развилок - мысль. Про np полноту - тоже.

Ок, спасибо.

Хотя наверное как всегда есть вариант комбинированный - чать отдается на "память" а часть на перебор...
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318373
ретти
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
softwarerКаждый раз, когда при добавлении ребра АБ уже имеем путь БА или - внимание - несколько таких путей, вот вам, бабушка, и циклы.
При всем моем, откуда такая зашоренность отклика на вторую сторону?
Переформулировать вопрос и считать его решенным.

Ваще децсад. "уже имеем путь БА". И как мы узнаем что мы его, этот путь, "уже имеем"(или, уже "поимели")?
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318378
ретти
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alexsalog softwarer AlexsalogПолучится дикое количество комбинаций......
Это если ребра добавляются интерактивно-то? Не очень верится, раньше оператор устанет :)

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

Насчет развилок - мысль. Про np полноту - тоже.

Ок, спасибо.

Хотя наверное как всегда есть вариант комбинированный - чать отдается на "память" а часть на перебор...
Этот тоже. Как Добчинский раскланялся. Типа спасибо. Насчет развилок -- это мысль?
Про эту банальщину тут никто и не вспоминал. Она тебе поможет как мертвому припарки.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318399
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
реттиВаще децсад. "уже имеем путь БА". И как мы узнаем что мы его, этот путь, "уже имеем"(или, уже "поимели")?
Ваш вопрос показывает, что Вы либо не читали то, на что отвечаете, либо временно/постоянно не в состоянии воспринимать прочитанное. До тех пор, пока означенные факторы не изменятся, беседа вряд ли будет осмысленной.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318413
asvdfdsv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
если речь только об интерактивной проверке, то проще и быстрее банально пускать волну из обеих вершин, которые соединяет новосозданное ребро
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318415
asvdfdsv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
asvdfdsvесли речь только об интерактивной проверке, то проще и быстрее банально пускать волну из обеих вершин, которые соединяет новосозданное ребро
из одной из этих вершин, разумеется, будет достаточно
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318421
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asvdfdsvесли речь только об интерактивной проверке, то проще и быстрее банально пускать волну
Если речь идет о том, чтобы найти какой-нибудь цикл, то да. Но автору нужны все - и тут не соглашусь, и не быстрее, и не проще.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318425
asvdfdsv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
softwarer asvdfdsvесли речь только об интерактивной проверке, то проще и быстрее банально пускать волну
Если речь идет о том, чтобы найти какой-нибудь цикл, то да. Но автору нужны все - и тут не соглашусь, и не быстрее, и не проще.
ну если все, тогда лучше конечно действительно строить маршруты
но опять же - на лету, имхо
т.е. если есть условие интерактивной проверки, то я бы по-любому это использовал, сужая задачу до поиска циклов, проходящих через заданную вершину (например их которой исходит новое ребро), а не ваааааще всех на графе
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318451
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asvdfdsvну если все, тогда лучше конечно действительно строить маршруты
но опять же - на лету, имхо
Интуитивное "имхо" желательно бы подкреплять. Одного гигабайта оперативки - столько есть на любой современной рабочей станции - хватит, чтобы хранить матрицу связности графа примерно на 90'000 вершин. Также память нужна будет под уже найденные циклы итп - но порядок величин понятен.

Сколько времени будет обсчитываться волна "из точки во все" на таком графе - довольно интересный вопрос. Заснуть, конечно, не успеешь, но вот получить ответ за комфортное для интерактивного режима время - далеко не факт.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318457
asvdfdsv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
softwarerОдного гигабайта оперативки - столько есть на любой современной рабочей станции - хватит, чтобы хранить матрицу связности графа примерно на 90'000 вершин.
мимо.
90к вершин орграфа без циклов может содержать, например,
600*(300 + 600 + 600^2 + 600^3 + ... + 600^299) ~ 7*10^827 маршрутов
(300 блоков вида (1вершина -> 300 вершин -> 1 вершина) соединенных последовательно)
кроме того.
мелкая софтиночка с ориентированными графами на гигабайт... извините, неприемлемо, тоже имхо, но подкреплять не буду.

softwarerСколько времени будет обсчитываться волна "из точки во все" на таком графе - довольно интересный вопрос. Заснуть, конечно, не успеешь, но вот получить ответ за комфортное для интерактивного режима время - далеко не факт.
подкреплять будете или как?)))
циклов в графе нет, все маршруты не превосходят по длине кол-ва вершин в графе, если при этом еще поколдовать над алгоритмом, учитывая точки "пересечения" маршрутов, то ваще шоколадно, но скорее всего и это не потребуется.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318458
asvdfdsv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
asvdfdsv600*(300 + 600 + 600^2 + 600^3 + ... + 600^299) ~ 7*10^827
ха ошибочка, на несколько порядков больше)))
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318477
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asvdfdsv90к вершин орграфа без циклов может содержать, например,
600*(300 + 600 + 600^2 + 600^3 + ... + 600^299) ~ 7*10^827 маршрутов
Угу. Это оценка сверху. А оценка снизу?

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

asvdfdsvподкреплять будете или как?)))
Нет, не буду. Также как и с маршрутами, числа гуляют на многие порядки - вследствие собственно прямой зависимости от количества маршрутов. Можно воспользоваться Вашей оценкой, данной выше: если, допустим, в оптимистическом варианте Вам удастся дать ответ за 1 микросекунду, сколько времени займет поиск при пессимистическом?
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318490
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer реттиВаще децсад. "уже имеем путь БА". И как мы узнаем что мы его, этот путь, "уже имеем"(или, уже "поимели")?
Ваш вопрос показывает, что Вы либо не читали то, на что отвечаете, либо временно/постоянно не в состоянии воспринимать прочитанное. До тех пор, пока означенные факторы не изменятся, беседа вряд ли будет осмысленной.
ой ну прямо ......
я подобной куйни нарешал воз и маленькую тележку.
И мгновенно определяю кто в теме, а кто нет.

А по существу я был абсолютно прав. Это ("уже имеем путь БА") звучит как насмешка.
Вроде топикстартер ну ваще дебил. А тут все умные.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318493
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Навеяло, http://acm.sgu.ru/problem.php?contest=0&problem=174

Ых, такие все умные. Пистец. Мне некуй доказывать. Я себя знаю. В софтверных конторах такого понимания самого себя хер получишь.
Не совсем то, конечно ( не орграф ), но я выделяю компоненты и раком и боком, и волновым.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318502
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Откуда ваще такие люди берутся?
Вот пишет: поступило на вход ребро 33-456. Проверь, нет ли пути 456--33.
Японский бох.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318504
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Замшелые сцуки & твари.
Он даже не может понять другую сторону.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318546
c127
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alexsalog softwarer FarusКто поможет: предложите алгорим определения цикличиеских ссылок на графе произвольного размера.
Зависит от того, что именно Вам нужно. Найти все циклы во всех вариантах? Найти фундаментальные циклы? Определить факт наличия циклов без поиска самих циклов? Еще что-нибудь?

И таки да, гугль содержит более чем достаточно информации на эту тему.

Найти любые циклы, притом если граф строится итеративно - то сообщить об этом цикле и показать его в момент добавления решающего ребра.

Т.е. ответить на вопрос присутствует ли в графе цикл или нет.

Графы считаем связными.

1) Дерево это граф без циклов. Это определение

2) Граф является деревом тогда и только тогда когда количество вершин на одну больше количества ребер. Это есть такая теорема.

Посчитайте ребра и вершины. Если строится итеративно, то и считайте итеративно, только следите за связностью.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318632
Николай1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rettyЗамшелые сцуки & твари.
Он даже не может понять другую сторону.
А закусить?
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35318641
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
c1272) Граф является деревом тогда и только тогда когда количество вершин на одну больше количества ребер. Это есть такая теорема.
Это есть теорема только для связных неориентированных графов. Если заменить "на одну больше" на "на на количество областей связности больше", видимо, можно обобщить на любые неориентированные графы. А вот с ориентированными, боюсь, труба.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35319139
c127
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
softwarer c1272) Граф является деревом тогда и только тогда когда количество вершин на одну больше количества ребер. Это есть такая теорема.
Это есть теорема только для связных неориентированных графов. Если заменить "на одну больше" на "на на количество областей связности больше", видимо, можно обобщить на любые неориентированные графы.

Со связностью все понятно, обобщается легко.

А вот с ориентированными, боюсь, труба.

Дейкстра. Как побочный эффект находит циклы неотрицательной длины. Его сложность по-моему лучше чем O(N**2) и по ребрам и по вершинам, и нетребователен к памяти, так что вполне. Но думаю что есть лучшие.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35319329
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Собсно, Дейкстра -- это разновидность волнового алгоритма.
Я вот тут накорябал. Только тяну не сумму стоимостей, а для каждой вершины тяну шлейф
из множества вершин, из которых можно попасть в нее. Вроде бы работает.

Например, trail[5] = {4, 7, 8, 9} значит что на каком-то этапе прохождения волны
мы увидели что в вершину № 5 можно попасть из вершин №№ 4, 7, 8, 9.
Эти хвосты, ес-но, будут расти и расти. Потом мы увидим, что проходя из вершины № 100
в вершину № 222, -- вершина № 222 входит в trail[100]. Т.е., обнаружен цикл.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
import sys
sys.stdin = open('E:/orgraph.txt','r')
n, m = map(int, sys.stdin.readline().split())
msm = [set([]) for i in range(n+ 1 )]
for i in range(m):
    v1, v2 = map(int, sys.stdin.readline().split())
    msm[v1].add(v2)
sys.stdin.close()

trail = [set() for i in range(n+ 1 )]
c = set()

def foo(a):
    global c
    c = c | a
    b = set()
    for x in a:
        for y in msm[x]:
            if y in trail[x]:
                return True
            trail[y] = trail[y] | trail[x] | set([x])
        b = b | msm[x]
    if b:
        return foo(b)
    return False
    
for z in range( 1 ,n+ 1 ):
    if not(z in c):
        res = foo(set([z]))
        if res:
            print 'Обнаружен цикл, проходящий через вершину №', z
            break
else:
    print 'Циклов нет'


------------- msm[0..N] -- это матрица смежности вида:
set([])
set([ 3 ,  4 ,  5 ])
set([ 5 ,  6 ,  7 ])
set([])
set([ 3 ])
set([])
set([ 1 ])
set([])
set([ 2 ,  7 ])
set([ 1 ,  11 ])
set([ 9 ])
set([ 10 ])

------------- в файле:
 11   14  ------- <-- число вершин и ребер (нумерую с единицы)
 1   5 
 4   3 
 8   2 
 2   7 
 2   5 
 2   6 
 6   1 
 1   4 
 1   3 
 8   7 
 9   1 
 9   11 
 11   10 
 10   9 
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35319368
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Взял 95-вершинный орграф, с 3710 ребром;
граф без циклов: по построению, все ребра идут от "меньшей" вершины к "большей".
Добавил 5 искусственных ребер, образующих цикл. Получил ответ:
Обнаружен цикл, проходящий через вершину № 33 (немного подправил код)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
 95   3715 
-- 76 18 -- добавки
-- 18 95 --
-- 95 33 --
-- 33 50 --
-- 50 76 --
 1   3 
 1   5 
 1   6 
 1   8 
 1   10 
 1   11 
 1   12 
 1   14 
 1   16 
 1   17 
.. ..
.. ..
 89   94 
 90   91 
 90   92 
 90   93 
 90   94 
 91   92 
 91   93 
 91   94 
 92   93 
 92   94 
 93   94 
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35319373
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asvdfdsv90к вершин орграфа без циклов может содержать, например,..
это да; если цикла/ов нет , то придется "ждать" , а если есть , то оно как-то быстро.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35319437
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добавил нюанс. В первом примере вершины №№ 9, 10 и 11 образуют вот такой междусобойчик:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
 11  --->-- 10
 \        /
  \_    |/_
  |\    /
    \  /
      9 
     |
     |
    \|/
     |
     |
Т.е., каждый раз, вернувшись из foo(), мы должны выкинуть из рассмотрения те вершины,
по которым прошла очередная волна. Т.е., идти вниз из № 9 к вершинам №№ 1 - 8 смысла нет никакого.
Мы больше там ничего нового не нароем. Типа так. Может и ошибаюсь.

На графе без циклов (95v3710e) получил ускорение ровно в 2 раза.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
import sys

#sys.stdin = open('E:/orgraph.txt','r')
sys.stdin = open('E:/p95v3710e.txt','r')
n, m = map(int, sys.stdin.readline().split())
msm = [set() for i in range(n+ 1 )]
for i in range(m):
    v1, v2 = map(int, sys.stdin.readline().split())
    msm[v1].add(v2)
sys.stdin.close()


trail = [set() for i in range(n+ 1 )]
c = set()

def foo(a):
    global c
    global trail
    c = c | a
    b = set()
    for x in a:
        for y in msm[x]:
            if y in trail[x]:
                return y
            trail[y] = trail[y] | trail[x] | set([x])
        b = b | msm[x]
    if b:
        return foo(b)
    return  0 


from time import time
t = time()

for z in range( 1 , n+ 1 ):
    if not(z in c):
        res = foo(set([z]))
        if res:
            print 'Обнаружен цикл, проходящий через вершину №', res
            break
        for j in range( 1 , n+ 1 ):
            if j in c:
                msm[j] = set()
            else:
                msm[j] = msm[j] - c
else:
    print 'Циклов нет'

print time() - t
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35319596
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот нарыл: http://www.geocities.com/Vienna/7079/src/graph.txt
Подсунул ему свой граф без циклов, обрезанный до 1000 ребер (там в комментах такое ограничение),
но ответа 'No cycles' так и не дождался. Может оно затыкается на одиноких висячих вершинах.
Я не разбирался. На 11-реберном графе ответ выдает какой надо.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
/*
For this program you will implement a graph cycle detector. The program
will
input a directed graph and output all simple cycles (see p88), if any,
that
exist in the graph. Specifically,

1.   Your program may use no global variables.

2.   Implement a graph data structure (either adjacency matrix or
adjacency
     list) to hold the directed graph. The graph must be allocated and
     deallocated at runtime. Implement procedures for graph allocation,
    graph deallocation, edge addition and edge lookup.

3.   Implement procedures for detecting (and outputting) cycles in a
given
     graph. A cycle should be output as a directed path starting from
the
     smallest vertex number, e.g., '1 -> 2 -> 3 -> 5 -> 1'. Cycles
should be
     output in non-decreasing order by their starting vertex, where
cycles
     beginning with the same vertex can be output in any order. If the
graph
     contains no cycles, then simply output 'No cycles'.

4.   The main part of your program will read in data from a file whose
name
     is given as the first argument to your executable. The first line
of
     the file contains the number of vertices (1-100) and edges (1-1000)
in
     the graph. The remaining lines define the edges in the graph in the
    form 'e 5 3', which means there is a directed edge in the graph from
    vertex 5 to vertex 3. Your main program should read in the graph and
    then call your procedure to output any cycles. 

*/

/* Anan Tongprasith */
/* Compile: cc graph.c */
/**********************/
#include<stdio.h>
#include<stdlib.h>

/* This program use adjacency matrix */

/************* list of all functions **************/

/* insert a new row in the middle of array ba */
int arrayshift(int ba[ 100 ][ 20 ],int i,int nodenum);

/* detect a cycle */
int cycledetec(int **A,int startp,int nodenum);

/* add an edge, m=start vertice, n=end vertice */
void graphadd(int **A,int m,int n);

/* allocate memory for the matrix */
int **graphalloc(int nodenum);

/* free memory */
void graphfree(int **A,int nodenum);

/**************************************************/

int main(int argc,char *argv[])
{ FILE *fp;char newline[ 10 ],*tempch=" ";
  int nodenum,edgenum,i,j,**A,mybegin,myend;

/* open the input file */
	fp=fopen(argv[ 1 ],"r");
	fgets(newline, 10 ,fp);

/* reading # of node */
	sscanf(newline,"%i %i",&nodenum,&edgenum);

/* allocating the adjacency matrix */
	A=graphalloc(nodenum);

/* reading the input file and adding to the matrix*/
	while(fgets(newline, 10 ,fp) != NULL)
	{ 
	   sscanf(newline,"%s %i %i",tempch,&mybegin,&myend);
	   graphadd(A,mybegin- 1 ,myend- 1 );
	}
	fclose(fp);
	j= 0 ;

/* detecting cycle from starting point i (1,2,3,4,5) */
	for(i= 0 ;i<nodenum;i++)
		if(cycledetec(A,i,nodenum)== 1 ) j+= 1 ;
	if(j== 0 )
		printf("No cycle\n");
	/*for(i=0;i<nodenum;i++)
	{
	  for(j=0;j<nodenum;j++)
	  	printf("%i ",A[i][j]);
	  printf("\n");
	}*/

/* freeing the matrix */
	graphfree(A,nodenum);
}

/* detect cycle beginning from startp */
/* how? brute force */
/* 1. find all existing paths with distance = mydist*/
/*    those paths must have really existing subpaths */
/* 2. put all those paths into "bigarray" */
/* 3. checking if those paths have redundant node? if so, throw away */
/* 4. checking if there is a path from the last node to the first node*/
/* 5. increase mydist and go back to 1. */
/****************************************/

int cycledetec(int **A,int startp,int nodenum)
{ int maxdist=nodenum-startp,cycle= 0 ,mydist,i,subdist,bigarray[ 100 ][ 20 ];
  int index,j,k,l;

/* checking for distance = 1, for examples, 4 -> 4, 3 -> 3 */ 
	if(A[startp][startp]== 1 )		/* mydist=0 */
	{  printf("%i -> %i\n",startp+ 1 ,startp+ 1 );
	   cycle= 1 ;
	}

/* checking for distance > 1 */
/****** outer loop check from distance = 2 to maximum distance
	(when startp=1) ********/

	for(mydist= 1 ;mydist<maxdist;mydist++) 
	{	
		for(i= 0 ;i< 100 ;i++)	/* assume possible route < 100 */
		{  for(index= 0 ;index<nodenum;index++)
		   bigarray[i][index]=- 1 ;
	   	   bigarray[i][ 0 ]=startp;
		}		/* this loop initialize the bigarray */
		index= 0 ;
/******* now start to fill in the bigarray **********/
/******* each row in the big array is an existing route *********/
/******* each possible route is already checked for existance of*****/
/******* subpath before being put in the bigarray ******/
/******* the bigarray are cleared when start looking the next distance */

	/* this subloop keep checking until reaching the wanted distance */	
	for(subdist= 1 ;subdist<=mydist;subdist++)  
		{
		   index= 0 ;

	/* node in the middle should be numbered less than starter */
		   for(i=startp+ 1 ;i<nodenum;i++)
		   {
			if(bigarray[index][subdist- 1 ]>= 0 &&A[bigarray[index][subdist- 1 ]][i]!= 0 ) /****** checking path from last point to current point *****/
			{	bigarray[index][subdist]=i;
				arrayshift(bigarray,index,nodenum);
				index+= 1 ;
				bigarray[index][subdist- 1 ]=bigarray[index- 1 ][subdist- 1 ];
			}
		   }
		}	
	/* After reaching the wanted distance, checking path from the
last nodes in all existing path back to the starting point */

		for(i= 0 ;i<index;i++)
		{	l= 0 ;

			/* this loop check for repeated node */
			/* ex. 1->3->3->4 , throw it away*/
			for(j= 0 ;j<=mydist;j++)
			{   for(k= 0 ;k<=mydist;k++)
			    {	if(j!=k && bigarray[i][j]==bigarray[i][k])
					l+= 1 ;
			    }
			}

			/* no repeated node? check for path from */
			/* the last node to startp */

			if(l== 0 &&A[bigarray[i][mydist]][startp]== 1 )
			{  for(j= 0 ;j<=mydist;j++)
			   	printf("%i -> ",bigarray[i][j]+ 1 );
			   printf("%i\n",startp+ 1 );
			   cycle= 1 ;	/* found a cycle */
			}
		}
	} 
	return cycle;
}
/* making rooms */
int arrayshift(int ba[ 100 ][ 20 ],int index,int nodenum)
{ int i,j;
	for(i= 98 ;i>index;i--)
	{  for(j= 0 ;j<nodenum;j++)
		ba[i+ 1 ][j]=ba[i][j];
	}
}
void graphadd(int **A,int m,int n)
{	A[m][n]= 1 ;
}
int **graphalloc(int nodenum)
{ int **A,i,j;
	A=malloc(nodenum* 8 );
	for(i= 0 ;i<nodenum;i++)
	{ A[i]=malloc(nodenum* 4 );
	  for(j= 0 ;j<nodenum;j++)
		A[i][j]= 0 ;
	}
	return A;
}
void graphfree(int **A,int nodenum)
{ int i;
	for(i= 0 ;i<nodenum;i++)
	{ free(A[i]);
	}
	free(A);
}
На всякий прилепил свой граф, без циклов.
Кстати, сишный код читает "научный" формат ребер: "e 5 3", а не просто "5 3".
Так что, если чего, то нужны поправки к коду.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35319624
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот кстати вспомнил.
МИПТовская задача: http://acm.mipt.ru/judge/problems.pl?problem=012
Похоже -- это наш сабж. Попробую сдать. Там питон в обойме языков.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35319766
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Продолбался как баран. Получил кучу runtime error. Пока не додумался обрезать свой код до предела.
У них питон версии 2.1.3. Я это знал, но не думал, что

5.7 sets -- Unordered collections of unique elements New in version 2.3.

=====
А built-in сет() появился еще позже. Короче, невезуха. Точнее, просто им плевать.
Этакий ненавязчивый сервис под соусом широты души. Или, как грили в стране советов: вас много, а я одна.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35320009
Alexsalog
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
retty softwarer реттиВаще децсад. "уже имеем путь БА". И как мы узнаем что мы его, этот путь, "уже имеем"(или, уже "поимели")?
Ваш вопрос показывает, что Вы либо не читали то, на что отвечаете, либо временно/постоянно не в состоянии воспринимать прочитанное. До тех пор, пока означенные факторы не изменятся, беседа вряд ли будет осмысленной.
ой ну прямо ......
я подобной куйни нарешал воз и маленькую тележку.
И мгновенно определяю кто в теме, а кто нет.

А по существу я был абсолютно прав. Это ("уже имеем путь БА") звучит как насмешка.
Вроде топикстартер ну ваще дебил. А тут все умные.

Мне просто лень думать и кроме того дефицит общения :-)

Я вот что придумал: "алгоритм реки" - название придумал сам (речь идет об ориентированном графе) :
все вершины располагаются в некой таблице по старшинству. то есть если стрелочка направлена из вершины А в вершину В, то А "старше" B. И в таблице "потока" они будут располагаться так:

Код: plaintext
1.
2.
3.
Level      Node
----------------
 1000         A 
 2000         B

Пусть теперь, из B выходит две стрелочки - одна в вершину С, а другая ИЗ вершины D.

Код: plaintext
1.
2.
3.
4.
          A--> B <---D
                \
                 \
                  _/
                   C
Значит, B "младше" D, но старше C. Узлы A и D равноправны. То есть имеем:

Код: plaintext
1.
2.
3.
4.
5.
Level      Node
----------------
 1000         A 
 1000         D
 2000         B
 3000         C

Как видим, если C станет "старше" D, то возникает цикл.
Идуцируем обобщение (пытаемся): при вставке в указанную таблицу новой вершины, располагая её по правилу иерархии с "родительской" вершиной мы не должны обнаружить её же выше себя самой. И наоборот. Вообщем, вершина не должна быть в двух местах по иерархии.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35321700
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то в этом есть. Если бы ребра поступали на вход без разрывов, так сказать.

Например, так: 1 -> 2 -> 3 -> 4 -> 5

Мы бы помечали предков:

№ 1 - предков нет
№ 2 - № 1
№ 3 - №№ 1, 2
№ 4 - №№ 1, 2, 3
№ 5 - №№ 1, 2, 3, 4

Теперь приходит ребро 5 -> 1. И мы сразу видим "противоречие":

№ 5 старше № 1, но № 1 входит в число его предков. Цикл.

А если ребро 2 -> 3 придет "позже всех"?
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35321797
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Глянул на свое решение вот этого http://www.spoj.pl/problems/PFDEP/ Топологическая сортировка, но с условием
Your program can assume that there are no circular dependencies in the rules, i.e. no task depends directly or indirectly on itself.
У меня там простейшая рекурсивная функция:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
procedure foo(r: longint);
var i: longint;
begin
inc(sch); h[sch]:=r; a[r, 0 ]:=- 1 ;
for i:= 1  to n do if a[i,r]= 1  then
begin dec(a[i, 0 ]); if a[i, 0 ]= 0  then foo(i); end;
end;
но что я в ней делаю... хоть убейте, не понимаю; проще заново решить.
Тем более не соображу можно ли сюда вставить проверку на зацикленность.
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35322074
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поставил себе питон-модуль networkx https://networkx.lanl.gov/download/networkx/networkx-0.36.win32.exe
Так он ацикличность моего графа на 3710 ребер определил в раз 110 быстрее моего ламерства.
По времени выглядит так как будто ему неважно есть в графе циклы или нет.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
import networkx as nx

g = nx.DiGraph()

import sys
sys.stdin = open('E:/p95.txt', 'r')
sys.stdin.readline()
for i in range( 3710 ):
    e = map(int, sys.stdin.readline().split())
    g.add_edge(e)
sys.stdin.close()


from time import time
t = time()

print nx.is_directed_acyclic_graph(g)

print time() - t




>>> 
True
 0 . 0150001049042 

И чиво там только нет:
>>> import networkx as nx
>>> dir(nx)
['DiGraph', 'Graph', 'LCF_graph', 'NetworkXError', 'NetworkXException', 'XDiGraph', 'XGraph', '__author__', '__builtins__', '__date__', '__doc__', '__file__', '__license__', '__name__', '__path__', '__version__', '_get_fh', 'adjlist', 'all_pairs_shortest_path', 'all_pairs_shortest_path_length', 'average_clustering', 'balanced_tree', 'barabasi_albert_graph', 'barbell_graph', 'betweenness_centrality', 'bidirectional_dijkstra', 'bidirectional_shortest_path', 'binomial_graph', 'brandes_betweenness_centrality', 'bull_graph', 'cartesian_product', 'center', 'centrality', 'chvatal_graph', 'circular_ladder_graph', 'cliques', 'cliques_containing_node', 'closeness_centrality', 'cluster', 'clustering', 'complement', 'complete_bipartite_graph', 'complete_graph', 'component', 'compose', 'configuration_model', 'connected_component_subgraphs', 'connected_components', 'connected_double_edge_swap', 'connected_smax_graph', 'convert', 'convert_node_labels_to_integers', 'convert_to_directed', 'convert_to_undirected', 'create_degree_sequence', 'create_empty_copy', 'cubical_graph', 'cumulative_distribution', 'cycle_graph', 'dag', 'degree', 'degree_centrality', 'degree_histogram', 'degree_sequence_tree', 'dense_gnm_random_graph', 'density', 'desargues_graph', 'dfs_postorder', 'dfs_predecessor', 'dfs_preorder', 'dfs_successor', 'dfs_tree', 'diameter', 'diamond_graph', 'digraph', 'dijkstra_path', 'dijkstra_path_length', 'dijkstra_predecessor_and_distance', 'discrete_sequence', 'disjoint_union', 'distance', 'dodecahedral_graph', 'dorogovtsev_goltsev_mendes_graph', 'double_edge_swap', 'drawing', 'eccentricity', 'edgelist', 'edges', 'edges_iter', 'empty_graph', 'erdos_renyi_graph', 'exception', 'expected_degree_graph', 'fast_gnp_random_graph', 'find_cliques', 'floyd_warshall', 'from_dict_of_dicts', 'from_dict_of_lists', 'from_numpy_matrix', 'from_scipy_sparse_matrix', 'from_whatever', 'frucht_graph', 'function', 'generators', 'gn_graph', 'gnc_graph', 'gnm_random_graph', 'gnp_random_graph', 'gnr_graph', 'gpickle', 'graph', 'graph_clique_number', 'graph_number_of_cliques', 'graphml', 'grid_2d_graph', 'grid_graph', 'havel_hakimi_graph', 'heapq', 'heawood_graph', 'house_graph', 'house_x_graph', 'hybrid', 'hypercube_graph', 'icosahedral_graph', 'info', 'is_connected', 'is_directed', 'is_directed_acyclic_graph', 'is_isomorphic', 'is_kl_connected', 'is_string_like', 'is_strongly_connected', 'is_valid_degree_sequence', 'isomorph', 'isomorphvf2', 'iterable', 'kl_connected_subgraph', 'kosaraju_strongly_connected_components', 'krackhardt_kite_graph', 'ladder_graph', 'leda', 'li_smax_graph', 'lollipop_graph', 'make_clique_bipartite', 'make_max_clique_graph', 'make_small_graph', 'math', 'moebius_kantor_graph', 'neighbors', 'networkx', 'newman_betweenness_centrality', 'newman_watts_strogatz_graph', 'node_clique_number', 'node_connected_component', 'nodes', 'nodes_iter', 'null_graph', 'number_connected_components', 'number_of_cliques', 'number_of_edges', 'number_of_nodes', 'number_strongly_connected_components', 'nx_yaml', 'octahedral_graph', 'operators', 'pappus_graph', 'pareto_sequence', 'parse_graph6', 'parse_graphml', 'parse_leda', 'parse_sparse6', 'path', 'path_graph', 'periphery', 'petersen_graph', 'powerlaw_cluster_graph', 'powerlaw_sequence', 'predecessor', 'radius', 'random', 'random_lobster', 'random_powerlaw_tree', 'random_powerlaw_tree_sequence', 'random_regular_graph', 'random_shell_graph', 'read_adjlist', 'read_edgelist', 'read_gpickle', 'read_graph6', 'read_graph6_list', 'read_graphml', 'read_leda', 'read_multiline_adjlist', 'read_sparse6', 'read_sparse6_list', 'read_yaml', 'readwrite', 'relabel_nodes', 'release', 's_metric', 'search', 'sedgewick_maze_graph', 'shortest_path', 'shortest_path_length', 'single_source_dijkstra', 'single_source_dijkstra_path', 'single_source_dijkstra_path_length', 'single_source_shortest_path', 'single_source_shortest_path_length', 'sparsegraph6', 'star_graph', 'strongly_connected_component_subgraphs', 'strongly_connected_components', 'strongly_connected_components_recursive', 'subgraph', 'test', 'tests', 'tetrahedral_graph', 'to_dict_of_dicts', 'to_dict_of_lists', 'to_numpy_matrix', 'to_scipy_sparse_matrix', 'topological_sort', 'topological_sort_recursive', 'transitivity', 'triangles', 'trivial_graph', 'truncated_cube_graph', 'truncated_tetrahedron_graph', 'tutte_graph', 'uniform_sequence', 'union', 'utils', 'watts_strogatz_graph', 'wheel_graph', 'write_adjlist', 'write_edgelist', 'write_gpickle', 'write_multiline_adjlist', 'write_yaml', 'xdigraph', 'xgraph']
>>>
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35322075
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вряд ли boost::graph или явавские библы менее богаты (если не более), в этом смысле;
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35322085
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот как выглядит их реализация проверки на ацикличность:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
import networkx

def is_directed_acyclic_graph(G):
    """Return True if the graph G is a directed acyclic graph (DAG).

    Otherwise return False.
    
    """
    if topological_sort(G) is None:
        return False
    else:
        return True

def topological_sort(G):
    """
    Return a list of nodes of the digraph G in topological sort order.

    A topological sort is a nonunique permutation of the nodes
    such that an edge from u to v implies that u appears before v in the
    topological sort order.

    If G is not a directed acyclic graph no topological sort exists
    and the Python keyword None is returned.

    This algorithm is based on a description and proof at
    http://www2.toki.or.id/book/AlgDesignManual/book/book2/node70.htm

    See also is_directed_acyclic_graph()
    
    """
    # nonrecursive version

    seen={}
    order_explored=[] # provide order and 
    explored={}       # fast search without more general priorityDictionary
                     
    if not G.is_directed():  G.successors_iter=G.neighbors_iter

    for v in G.nodes_iter():     # process all vertices in G
        if v in explored: continue

        fringe=[v]   # nodes yet to look at
        while fringe:
            w=fringe[- 1 ]  # depth first search
            if w in explored: # already looked down this branch
                fringe.pop()
                continue
            seen[w]= 1      # mark as seen
            # Check successors for cycles and for new nodes
            new_nodes=[]
            for n in G.successors_iter(w):  
                if n not in explored:
                    if n in seen: return #CYCLE !!
                    new_nodes.append(n)
            if new_nodes:   # Add new_nodes to fringe
                fringe.extend(new_nodes)
            else:           # No new nodes so w is fully explored
                explored[w]= 1 
                order_explored.insert( 0 ,w) # reverse order explored
                fringe.pop()    # done considering this node
    return order_explored

def topological_sort_recursive(G):
    """
    Return a list of nodes of the digraph G in topological sort order.

    This is a recursive version of topological sort.
    
    """
    # function for recursive dfs
    def _dfs(G,seen,explored,v):
        seen[v]= 1 
        for w in G.successors(v):
            if w not in seen: 
                if not _dfs(G,seen,explored,w):
                    return
            elif w in seen and w not in explored:
                # cycle Found--- no topological sort
                return False
        explored.insert( 0 ,v) # inverse order of when explored 
        return v

    seen={}
    explored=[]

    if not G.is_directed():  G.successors=G.neighbors
    
    for v in G.nodes_iter():  # process all nodes
        if v not in explored:
            if not _dfs(G,seen,explored,v): 
                return 
    return explored
...
Рейтинг: 0 / 0
Алгоритм определения циклических ссылок
    #35322132
retty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexsalogЯ вот что придумал: "алгоритм реки" - название придумал сам (речь идет об ориентированном графе) :
все вершины располагаются в некой таблице по старшинству. то есть если стрелочка направлена из вершины А в вершину В, то А "старше" B. И в таблице "потока" они будут располагаться так:

Код: plaintext
1.
2.
3.
Level      Node
----------------
 1000         A 
 2000         B

Пусть теперь, из B выходит две стрелочки - одна в вершину С, а другая ИЗ вершины D.

Код: plaintext
1.
2.
3.
4.
          A--> B <---D
                \
                 \
                  _/
                   C
Значит, B "младше" D, но старше C. Узлы A и D равноправны. То есть имеем:

Код: plaintext
1.
2.
3.
4.
5.
Level      Node
----------------
 1000         A 
 1000         D
 2000         B
 3000         C

Как видим, если C станет "старше" D, то возникает цикл.
Идуцируем обобщение (пытаемся): при вставке в указанную таблицу новой вершины , располагая её по правилу иерархии с "родительской" вершиной мы не должны обнаружить её же выше себя самой. И наоборот. Вообщем, вершина не должна быть в двух местах по иерархии.
Я вообще-то пляшу от вставки нового ребра (неважно, появились ли после этой вставки новые вершины или нет),
и в припадке ламеризьма накарябал код для интерактивного ввода ребер.
Пусть и не эффективный (?). Все равно, я думаю, что даже это будет работать достаточно быстро (на своем файле я даже время не засекал -- ответ выдает мгновенно -- это же вам не питон).

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <bitset>
#include <vector>

using namespace std;

const int n= 1000 ;     //--ожидаемое число вершин; нумеруем с 1

bitset<n+ 1 > np;     //--битсет для обновления списков предков части вершин
bitset<n+ 1 > pr[n+ 1 ];  //--в этих битсетах храним списки предков всех вершин
vector<int> msm[n+ 1 ];   //--матрица смежности
vector<int> v( 1 );
int v1,v2;
int res;


int foo(vector<int> &v) {
    vector<int> w;
    for (int i= 0 ; i<v.size(); ++i) {
        if (np.test(v[i])) return v[i]; //-- в добавочном списке предков
                           //-- обнаружена сама вершина v[i]! -- Цикл!
        pr[v[i]]=pr[v[i]] | np; //-- обновляем список предков вершины v[i]
        w.insert(w.end(),msm[v[i]].begin(),msm[v[i]].end()); //-- формируем
                                                             //-- новую волну
    }
    if (w.empty()) return  0 ;
    else return foo(w); //-- гоним очередной гребень, если есть что гнать
}


FILE *fp=fopen("E:\\p95.txt","r");

int main() {
    for (int j= 0 ; j< 3710 ; ++j) {
        fscanf(fp,"%d%d",&v1,&v2);   //-- читаем очередное ребро (v1 -> v2)
        msm[v1].push_back(v2);     //-- добавляем в матрицу смежности
        np=pr[v1];               //-- это битсет для обновления списков предков
        np.set(v1);               //-- ставим бит и для v1
        v[ 0 ]=v2;                   //-- начинаем обновление с вершины v2
        res=foo(v);                 //-- гоним волну от вершины v2
        if (res!= 0 ) {
            cout << "Cycle at vertex #" << res << "\n";
            break;
        }
    }

    fclose(fp);
    if (res== 0 ) cout << "No cycles!\n";

cin >> res;
return  0 ;
}
...
Рейтинг: 0 / 0
50 сообщений из 50, показаны все 2 страниц
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Алгоритм определения циклических ссылок
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]