Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Алгоритм поиска длинейшего пути в графике.

305  
format c:\u посетитель17.01.07 21:20
NEW 17.01.07 21:20 
Уже 2 дня ломаю голову. Вздрагиваю при взглюде на любую карту. Перерыл теорию графиков. Нашел множество алгоритмов на нахождение коротчайшего пути в графике без циклов. А с циклами вооще неодного. Может быть кто нибудь сталкивался с похожей задачей. Или знает где найти информацию. Предложениям и идеям буду рад.
Задача выглядит примерно так.
Дано= Ненаправленный циглический график. Тоесть растояние от А на А не всегда =0 и от А на Б может быть несколько возможных путей.
Задача= Найти длинейший путь. Так что бы кажое соединение было только один раз.(Как бы нарисовать неотрывая руки ) К примеру если есть A->A>0 тогда выбирать этот путь. И если есть несколько возможностей А->Б то выбирать длинейший.
Структура данных выглядит так:
Knote{ int ID}
Kante {Knote a , Knote b , int laenge}
Graph{ArrayList <Kante> kanten }
#1 
  scorpi_ скептик17.01.07 21:57
NEW 17.01.07 21:57 
в ответ format c:\u 17.01.07 21:20, Последний раз изменено 17.01.07 22:23 (scorpi_)
Графов, а не графиков. Кратчайший путь между двумя узлами находится с помощью алгоритма Дейкстры - http://de.wikipedia.org/wiki/Dijkstra-Algorithmus. Странно, что ты его не нашёл, этот алгоритм в теории графов дают обычно самым первым.
PS Наличие/отсутствие циклов этот алгоритм вообще мало волнует.
PPS Тут и программировать ничего не надо, берёшь буст и считаешь. Вот готовый пример - http://www.boost.org/libs/graph/example/dijkstra-example.cpp
PPPS ОК, забудь. Ты меня сбил с толку неточной постановкой вопроса.
#2 
Tomasson знакомое лицо17.01.07 22:00
Tomasson
NEW 17.01.07 22:00 
в ответ scorpi_ 17.01.07 21:57
Кратчайший путь между двумя узлами находится с помощью алгоритма Дейкстры
он же про *длинейший путь* молвит.
#3 
  scorpi_ скептик17.01.07 22:04
NEW 17.01.07 22:04 
в ответ Tomasson 17.01.07 22:00, Последний раз изменено 17.01.07 22:14 (scorpi_)
А, сейчас дошло. Он меня сбил своими рассуждениями о кратчайшем пути.
#4 
  scorpi_ скептик17.01.07 22:28
NEW 17.01.07 22:28 
в ответ format c:\u 17.01.07 21:20
По-моему метод ветвей и границ должен сработать. Пишем минус бесконечность в несуществующие рёбра и ищем максимум.
#5 
format c:\u посетитель17.01.07 23:49
NEW 17.01.07 23:49 
в ответ scorpi_ 17.01.07 22:28, Последний раз изменено 18.01.07 23:09 (format c:\u)
Помоему ты меня неправильно понял или я неправильно понял метод метода ветвей и границ. Помоему этот метод не пойдет. Я прикрипил jpg-шку. с примером. Стрелки во внимание не принимать.
Алгоритм должен выдать AB-BC-СD-DB-BE-EF-FG-GH-HI-IJ-JL-LF-FM-MN . Если предположить что длина каждого соединения одинакова. Причем без разницы в каком порядке. Или хотябы AB.laenge + BC.laenge +......+ MN.laenge.
#6 
Murr коренной житель18.01.07 00:35
Murr
NEW 18.01.07 00:35 
в ответ format c:\u 17.01.07 23:49
Смотри по ключевым словам Задача Комивояжера.
#7 
format c:\u посетитель18.01.07 09:38
18.01.07 09:38 
в ответ Murr 18.01.07 00:35
Комивояжор должен проехать все города по минимальному пути заезжая в каждый город один раз. Мне же проезжать все городе не надо да и в города заезжать я могу много раз. А вот проезжать по одному и томожу пути я могу только один раз.
#8 
Murr коренной житель18.01.07 09:44
Murr
NEW 18.01.07 09:44 
в ответ format c:\u 18.01.07 09:38
Ну тогда придется комбинировать что-то типа Волны (см. трассировка печатных плат, метод волны) и перебора.
И насколько точно надо посчитать? Обычно можно не считать, а обойтись приблизительной верхней оценкой.
#9 
format c:\u завсегдатай18.01.07 10:39
NEW 18.01.07 10:39 
в ответ Murr 18.01.07 09:44
Надо точно.
#10 
AlterEgo Чеширръ18.01.07 11:16
AlterEgo
NEW 18.01.07 11:16 
в ответ format c:\u 18.01.07 10:39, Последний раз изменено 18.01.07 11:20 (AlterEgo)
Помоему можно модифицировать Дейкстру
перебираем все маршруты помечая посещенные узлы, попутно запоминая максимальное расстояния до узла. (C#)
// Program.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace LongestWay {
class Node {
public List<Edge> Edges = new List<Edge>();
public bool Visited = false;
public double MaxDistance = 0d;
public List<Node> LongestWay;
public void WalkIn(double distance, Stack<Nodes> way) {
if (Visited) return;
Visited = true;
if (distance > MaxDistance) {
MaxDistance = distance;
LongestWay = new List<Node>(way);
}
way.Push(this);
foreach (Edge edge in Edges) {
edge.Node.WalkIn(distance + edge.Length);
}
way.Pop();
Visited = false;
}
public override string ToString() {
// dump results
return string.Format("MaxDistance: {0}",MaxDistance);
}
}
class Edge {
public double Length;
public Node Node;
}
class Program {
static void Main(string[] args) {
List<Node> nodes = new List<Node>();
Node start = new Node();
/* hier fill nodes, edges and set start node */
foreach (Node node in nodes) {
node.MaxDistance = 0d;
node.Visited = false;
}
start.WalkIn(0d, new Stack<Nodes>());
foreach (Node node in nodes)
Console.WriteLine(node);
}
}
}

*Ъ...
#11 
Russman коренной житель18.01.07 12:54
Russman
NEW 18.01.07 12:54 
в ответ format c:\u 18.01.07 10:39
Есть способ вычисления всех "уникальных" путей в системе. Потом можно быбрать самый длинный.
S. Schuster and C. Hilgetag: On Elementary Flux Modes in Biochemical Reaction Systems at Steady State, Journal of Biological Systems 2, 1994, 165-182.
---
Хорошо когда собака - друг, но плохо, когда друг - собака.
#12 
format c:\u завсегдатай18.01.07 23:06
NEW 18.01.07 23:06 
в ответ AlterEgo 18.01.07 11:16
Не получится. Если помечать узлы тогда циклы не будут считатся. А если помечать соединения тогда путь не всегда получается длинейшим, если к примеру первым был выбран путь который короче. Если ничего не помечать тогда бегаем по кругу.
#13 
AlterEgo Чеширръ18.01.07 23:38
AlterEgo
NEW 18.01.07 23:38 
в ответ format c:\u 18.01.07 23:06, Последний раз изменено 19.01.07 01:00 (AlterEgo)
Действительно, ответ немного не на ту задачу. Но я не понял в чем проблема если помечать соединения и в каждом узле перебирать все соединения которые до сих пор не помечены?
Рекурсивно переберем все возможные пути.
Что касается путей само на себя (A->A) то их просто добавлять к общему пути при первом посещении узла А. В принципе перебор их тоже посчитает, но так быстрее будет.
*Ъ...
#14 
format c:\u завсегдатай19.01.07 09:01
NEW 19.01.07 09:01 
в ответ AlterEgo 18.01.07 23:38, Последний раз изменено 19.01.07 09:03 (format c:\u)
Алгоритм почти работает но:
Правильный результат можно получить только если стартовать с точки A или N.
если начать в точке N тогды на узле F три возможности дальнейшего пути. На G на L и на E. Если алгоритм выбирит в первую очередь L или G тогда все нормально. но если пойдет на E в первую очередь тогды все точки от E начиная влево будут иметь не максимальное растояние. Так как цикл FGHIJLF не учитывается.
Если начать с A таже история.
#15 
AlterEgo Чеширръ19.01.07 17:31
AlterEgo
NEW 19.01.07 17:31 
в ответ format c:\u 19.01.07 09:01
Все работает. если не останавливать перебор после того как дошли до заданной точки алгоритм найдет и короткий путь и пути содержащие циклы FGHIJLF и FLJIHGF.
Суть в том что ищутся все возможные пути.
Что мне код написать, что бы понятно стало?
*Ъ...
#16 
katran76 местный житель22.01.07 07:59
NEW 22.01.07 07:59 
в ответ format c:\u 17.01.07 21:20
Я хренею дарагая ридакцея.
1. Заменяешь расстояния x -> 1/x (т.е. вместо 2 ставишь 1/2=0.5,
вместо 4 имеем 1/4=0.25 и т.д.)
2. Находишь любым из известных способом кратчайший путь
(кратчайший путь для обратных расстояний и будет длиннейшим для оригинальных расстояний)

#17 
AlterEgo Чеширръ22.01.07 08:32
AlterEgo
NEW 22.01.07 08:32 
в ответ katran76 22.01.07 07:59
1. Заменяешь расстояния x -> 1/x (т.е. вместо 2 ставишь 1/2=0.5,
вместо 4 имеем 1/4=0.25 и т.д.)
из того что 1/a + 1/b > 1/c + 1/d не следует что с+d > a + b
пример 0.5 + 0.5 < 0.1 + 1 и 1/0.5 + 1/0.5 < 1/0.1 + 1/1
так что не пойдет
*Ъ...
#18 
katran76 местный житель22.01.07 12:40
NEW 22.01.07 12:40 
в ответ AlterEgo 22.01.07 08:32
Ой
а жаль
#19 
desyman свой человек23.01.07 11:24
desyman
NEW 23.01.07 11:24 
в ответ format c:\u 17.01.07 21:20, Последний раз изменено 23.01.07 11:26 (desyman)
кажися кроме как перебором не решается,
возможно упрошение типа: отбросить тупиковые ветви
(ветви, узлы которых не являются началом и концом "путешествия" и у каждого не более 2 связей)
хотя это еше как делать перебор, может это упрошние и не нужно вовсе
#20