Полный граф только с двумя возможными затратами. Какова стоимость кратчайшего пути от 0 до N - 1

Вам дан полный неориентированный граф с N вершинами. Все ребра, кроме K, имеют стоимость A. Эти K ребер имеют стоимость B, и вы знаете их (как список пар). Какова минимальная стоимость от узла 0 до узла N - 1.

2 <= N <= 500k
0 <= K <= 500k
1 <= A, B <= 500k 

Проблема, очевидно, заключается в том, что эти K ребер стоят больше, чем другие, а узел 0 и узел N - 1 соединены K-ребром.

Дийкстра не работает. Я даже пробовал что-то очень похожее с BFS.

Step1: Let G(0) be the set of "good" adjacent nodes with node 0.
Step2: For each node in G(0):
              compute G(node)
              if G(node) contains N - 1
                  return step

              else
                  add node to some queue
       repeat step2 and increment step

Проблема в том, что на это уходит много времени из-за того, что для каждого узла приходится делать цикл от 0 до N - 1, чтобы найти "хорошие" соседние узлы.

У кого-нибудь есть идеи получше? Спасибо.

Изменить: вот ссылка с конкурса ACM: http://acm.ro/prob/probleme/B.pdf


person fanton    schedule 12.04.2014    source источник
comment
Также возникает проблема, когда A › B и ребро от 0 до N-1 стоит A. В этом случае вы можете сформировать путь k*B ‹ A.   -  person Gassa    schedule 12.04.2014
comment
Да, но на самом деле это не проблема, потому что у вас всего 500 000 B-краев. И вы можете позволить себе выполнение BFS на графе с B-ребрами. Проблема в том, что вам нужно исследовать дополнительный граф (потому что это дешевые ребра).   -  person fanton    schedule 12.04.2014
comment
Что значит, Дийкстра не работает? Это слишком дорого, или есть что-то в проблеме, из-за которой он выходит из строя?   -  person user2357112 supports Monica    schedule 12.04.2014
comment
Я имею в виду, что Дийктра требует слишком много времени для решения этой проблемы. O (E * logV) означает примерно 10 ^ 15 операций в худшем случае. Слишком много.   -  person fanton    schedule 12.04.2014
comment
@FlaviusAnton Эта проблема где-то в сети? Я хотел бы решить это   -  person Niklas B.    schedule 12.04.2014
comment
@НикласБ. Не совсем. Я видел это в школьном задании (не моём, понятно?) и привлек моё внимание. Я также слышал слухи, что он изначально использовался в конкурсе ACM, но я не смог его найти.   -  person fanton    schedule 13.04.2014
comment
На самом деле это так. Вот ссылка, я как-то ее нашел: acm.ro/prob/probleme/B. pdf   -  person fanton    schedule 15.04.2014
comment
@FlaviusAnton Спасибо. К моему удивлению, решение O(n log n + m * (log m + log n)) segtree прошло без каких-либо оптимизаций. О проблеме можно судить онлайн в живом архиве ICPC   -  person Niklas B.    schedule 16.04.2014


Ответы (4)


Это кропотливая работа над делом:

  1. A ‹ B и 0 и N-1 соединены A -> тривиальным.
  2. B ‹ A и 0 и N-1 соединены B -> тривиальным.
  3. B ‹ A и 0 и N-1 соединены A -> Do BFS на графе только с K ребрами.
  4. A ‹ B и 0 и N-1 соединены B -> Вы можете проверить за время O (N), существует ли путь длиной 2 * A (попробуйте каждую вершину в середине).

    Чтобы проверить другие длины пути, следующий алгоритм должен помочь: пусть X (d) будет набором узлов, достижимых с использованием d более коротких ребер из 0. Вы можете найти X (d), используя следующий алгоритм: Возьмите каждую вершину v с неизвестным расстоянием и итеративно проверить ребра между v и вершинами из X(d-1). Если вы нашли короткое ребро, то v находится в X(d), иначе вы наступили на длинное ребро. Так как существует не более K длинных ребер, вы можете наступить на них не более K раз. Таким образом, вы должны найти расстояние до каждой вершины не более чем за время O(N + K).

person usamec    schedule 12.04.2014
comment
Это не совсем правильно. У меня есть пример графа со 120 000 узлов, хорошие ребра стоят 1, а плохие — 100 000, а кратчайший путь имеет длину 5, что больше 3. - person fanton; 12.04.2014

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

Вы можете использовать дерево сегментов, чтобы сделать работу Дейкстры более эффективной. Вам понадобятся операции

  • установить верхнюю границу в диапазоне, как в заданных U, L, R; для всех x[i] с L ‹= i ‹= R, установите x[i] = min(x[i], u)
  • найти глобальный минимум

Верхние границы можно лениво сдвигать вниз по дереву, поэтому оба варианта можно реализовать за O(log n)

При ослаблении исходящих ребер ищите ребра со стоимостью B, сортируйте их и обновляйте диапазоны между ними сразу.

Время выполнения должно быть O (n log n + m log m), если вы отсортируете все ребра заранее (по исходящей вершине).

EDIT: этот подход был принят. Хорошая вещь об этом заключается в том, что он избегает каких-либо специальных корпусов. Это все еще ~80 строк кода.

person Niklas B.    schedule 12.04.2014

В случае, когда A ‹ B, я бы использовал своего рода BFS, где вы бы проверяли, куда вы не можете добраться, а не туда, где вы можете. Вот псевдокод:

G(k) is the set of nodes reachable by k cheap edges and no less. We start with G(0) = {v0}

while G(k) isn't empty and G(k) doesn't contain vN-1 and k*A < B
  A = array[N] of zeroes
  for every node n in G(k)
    for every expensive edge (n,m)
      A[m]++
  # now we have that A[m] == |G(k)| iff m can't be reached by a cheap edge from any of G(k)
  set G(k+1) to {m; A[m] < |G(k)|} except {n; n is in G(0),...G(k)}
  k++

Таким образом, вы избегаете повторения (много) дешевых ребер и перебираете только относительно небольшое количество дорогих ребер.

person voidengine    schedule 12.04.2014

Как вы правильно заметили, проблема возникает, когда A > B и ребро от 0 до n-1 имеет стоимость A.

В этом случае вы можете просто удалить в графе все ребра со стоимостью A. Это потому, что оптимальный маршрут должен иметь только ребра со стоимостью B.

Затем вы можете выполнить простую BFS, поскольку стоимость всех ребер одинакова. Это даст вам оптимальную производительность, как указано в этой ссылке: Поиск кратчайшего пути для равных взвешенный график

Более того, вы можете остановить свой BFS, когда общая стоимость превысит A.

person Abhishek Bansal    schedule 12.04.2014
comment
Вы, конечно, правы, но это мелочи. Я говорю как раз о противоположном случае, когда те K ребер (которых меньше) дороже. Потому что тогда вам придется выполнять BFS на дополнительном графе, который имеет гораздо больше ребер. - person fanton; 12.04.2014
comment
Тот же алгоритм можно применить и в вашем противоположном случае. Ссылка, которую я указал, показывает, что BFS — лучший подход к решению этой проблемы. Вам не нужно каждый раз зацикливаться от 0 до N-1, если вы удалите ненужные ребра до BFS. - person Abhishek Bansal; 12.04.2014