blog/algorithms/paths/bf-to-astar/dijkstra/index.html

145 lines
90 KiB
HTML
Raw Normal View History

<!doctype html>
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-algorithms docs-version-current docs-doc-page docs-doc-id-paths/2024-01-01-bf-to-astar/dijkstra" data-has-hydrated="false">
<head>
<meta charset="UTF-8">
<meta name="generator" content="Docusaurus v3.1.1">
<title data-rh="true">Dijkstra&#x27;s algorithm | mf</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://blog.mfocko.xyz/algorithms/paths/bf-to-astar/dijkstra/"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-algorithms-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-algorithms-current"><meta data-rh="true" property="og:title" content="Dijkstra&#x27;s algorithm | mf"><meta data-rh="true" name="description" content="Moving from Bellman-Ford into the Dijsktra&#x27;s algorithm.
"><meta data-rh="true" property="og:description" content="Moving from Bellman-Ford into the Dijsktra&#x27;s algorithm.
"><link data-rh="true" rel="icon" href="/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://blog.mfocko.xyz/algorithms/paths/bf-to-astar/dijkstra/"><link data-rh="true" rel="alternate" href="https://blog.mfocko.xyz/algorithms/paths/bf-to-astar/dijkstra/" hreflang="en"><link data-rh="true" rel="alternate" href="https://blog.mfocko.xyz/algorithms/paths/bf-to-astar/dijkstra/" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://0VXRFPR4QF-dsn.algolia.net" crossorigin="anonymous"><link rel="search" type="application/opensearchdescription+xml" title="mf" href="/opensearch.xml">
<link rel="alternate" type="application/rss+xml" href="/blog/rss.xml" title="mf RSS Feed">
<link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" title="mf Atom Feed">
<link rel="alternate" type="application/json" href="/blog/feed.json" title="mf JSON Feed">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css" integrity="sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM" crossorigin="anonymous"><link rel="stylesheet" href="/assets/css/styles.e1ac7597.css">
<script src="/assets/js/runtime~main.f2ae61cf.js" defer="defer"></script>
<script src="/assets/js/main.237fcc8a.js" defer="defer"></script>
</head>
<body class="navigation-with-keyboard">
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return localStorage.getItem("theme")}catch(t){}}();t(null!==e?e:"light")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><b class="navbar__title text--truncate">mf</b></a><div class="navbar__item dropdown dropdown--hoverable"><a href="#" aria-haspopup="true" aria-expanded="false" role="button" class="navbar__link">Additional FI MU materials</a><ul class="dropdown__menu"><li><a aria-current="page" class="dropdown__link dropdown__link--active" href="/algorithms/">Algorithms</a></li><li><a class="dropdown__link" href="/c/">C</a></li><li><a class="dropdown__link" href="/cpp/">C++</a></li></ul></div><a class="navbar__item navbar__link" href="/contributions/">Contributions</a><a class="navbar__item navbar__link" href="/talks/">Talks</a></div><div class="navbar__items navbar__items--right"><a class="navbar__item navbar__link" href="/blog/">Blog</a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type="button" disabled="" title="Switch between dark and light mode (currently light mode)" aria-label="Switch between dark and light mode (currently light mode)" aria-live="polite"><svg viewBox="0 0 24 24" width="24" height="24" class="lightToggleIcon_pyhR"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" class="darkToggleIcon_wfgR"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg></button></div><div class="navbarSearchContainer_Bca1"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.
<p>Let&#x27;s rewind back to the small argument in the previous post about the fact that
we can safely bound the amount of iterations with relaxations being done.</p>
<p>We have said that assuming the worst-case scenario (bad order of relaxations) we
<strong>need</strong> at most <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal"></mi><mi>V</mi><mi mathvariant="normal"></mi><mo></mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\vert V \vert - 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.22222em">V</span><span class="mord"></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin"></span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:0.6444em"></span><span class="mord">1</span></span></span></span> iterations over all edges. We&#x27;ve used that
to our advantage to <em>bound</em> the iterations instead of the <code>do-while</code> loop that
was a risk given the possibility of the infinite loop (when negative loops are
present in the graph).</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>We could&#x27;ve possibly used both <em>boolean flag</em> to denote that some relaxation has
happened and the upper bound of iterations, for some graphs that would result in
faster termination.</p><p>Using only the upper bound we try to relax edges even though we can&#x27;t.</p></div></div>
<p>Now the question arises, could we leverage this somehow in a different way? What
if we used it to improve the algorithm instead of just bounding the iterations?
Would that be even possible?</p>
<p><strong>Yes, it would!</strong> And that&#x27;s when <em>Dijkstra&#x27;s algorithm</em> comes in.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="dijkstras-algorithm">Dijkstra&#x27;s algorithm<a href="#dijkstras-algorithm" class="hash-link" aria-label="Direct link to Dijkstra&#x27;s algorithm" title="Direct link to Dijkstra&#x27;s algorithm"></a></h2>
<p>I&#x27;ll start with a well-known meme about Dijkstra&#x27;s algorithm:
<img decoding="async" loading="lazy" alt="Dijkstra&amp;#39;s algorithm meme" src="/assets/images/dijkstra-meme-405d6b8dcc7aec5846fef402abfa8317.jpg" width="960" height="724" class="img_ev3q"></p>
<p>And then follow up on that with the actual backstory from Dijkstra himself:</p>
<blockquote>
<p>What is the shortest way to travel from Rotterdam to Groningen, in general:
from given city to given city. It is the algorithm for the shortest path,
which I designed in about twenty minutes. One morning I was shopping in
Amsterdam with my young fiancée, and tired, we sat down on the café terrace to
drink a cup of coffee and I was just thinking about whether I could do this,
and I then designed the algorithm for the shortest path. As I said, it was
a twenty-minute invention. In fact, it was published in &#x27;59, three years
later. The publication is still readable, it is, in fact, quite nice. One of
the reasons that it is so nice was that I designed it without pencil and
paper. I learned later that one of the advantages of designing without pencil
and paper is that you are almost forced to avoid all avoidable complexities.
Eventually, that algorithm became to my great amazement, one of the
cornerstones of my fame.</p>
<p>— Edsger Dijkstra, in an interview with Philip L. Frana, Communications of the
ACM, 2001</p>
</blockquote>
<div class="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Precondition</div><div class="admonitionContent_BuS1"><p>As our own naïve algorithm, Dijkstra&#x27;s algorithm has a precondition that places
a requirement of <em>no edges with negative weights</em> in the graph. This
precondition is required because of the nature of the algorithm that requires
monotonically non-decreasing changes in the costs of shortest paths.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="short-description">Short description<a href="#short-description" class="hash-link" aria-label="Direct link to Short description" title="Direct link to Short description"></a></h2>
<p>Let&#x27;s have a brief look at the pseudocode taken from the Wikipedia:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">function Dijkstra(Graph, source):</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> for each vertex v in Graph.Vertices:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> dist[v] ← INFINITY</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> prev[v] ← UNDEFINED</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> add v to Q</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> dist[source] ← 0</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> while Q is not empty:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> u ← vertex in Q with min dist[u]</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> remove u from Q</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> for each neighbor v of u still in Q:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> alt ← dist[u] + Graph.Edges(u, v)</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> if alt &lt; dist[v]:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> dist[v] ← alt</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> prev[v] ← u</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> return dist[], prev[]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Dijkstra&#x27;s algorithm works in such way that it always tries to find the shortest
paths from a vertex to which it already has a shortest path. This may result in
finding the shortest path to another vertex, or at least some path, till further
relaxation.</p>
<p>Given that we need to <strong>always</strong> choose the <em>cheapest</em> vertex, we can use a min
heap to our advantage which can further improve the time complexity of the
algorithm.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="used-techniques">Used techniques<a href="#used-techniques" class="hash-link" aria-label="Direct link to Used techniques" title="Direct link to Used techniques"></a></h2>
<p>This algorithm leverages the <em>dynamic programming</em> technique that has already
been mentioned with regards to the <em>Bellman-Ford</em> algorithm and also <em>greedy</em>
technique. Let&#x27;s talk about them both!</p>
<p><em>Dynamic programming</em> technique comes from the fact that we are continuously
building on top of the shortest paths that we have found so far. We slowly build
the shortest paths from the given source vertex to all other vertices that are
reachable.</p>
<p><em>Greedy</em> technique is utilized in such way that Dijkstra&#x27;s algorithm always
improves the shortest paths from the vertex that is the closest, i.e. it tries
extending the shortest path to some vertex by appending an edge, such extended
path may (or may not) be the shortest path to another vertex.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Greedy algorithms</div><div class="admonitionContent_BuS1"><p><em>Greedy algorithms</em> are algorithms that choose the most optimal action
<strong>at the moment</strong>.</p></div></div>
<p>The reason why the algorithm requires no edges with negative weights comes from
the fact that it&#x27;s greedy. By laying the requirement of non-negative weights in
the graph we are guaranteed that at any given moment of processing outgoing
edges from a vertex, we already have a shortest path to the given vertex. This
means that either this is the shortest path, or there is some other vertex that
may have a higher cost, but the outgoing edge compensates for it.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implementation">Implementation<a href="#implementation" class="hash-link" aria-label="Direct link to Implementation" title="Direct link to Implementation"></a></h2>
<p>Firstly we need to have some priority queue wrappers. C++ itself offers
functions that can be used for maintaining max heaps. They also have generalized
version with any ordering, in our case we need reverse ordering, because we need
the min heap.</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">using</span><span class="token plain"> pqueue_item_t </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">pair</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> vertex_t</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">using</span><span class="token plain"> pqueue_t </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">vector</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">pqueue_item_t</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">auto</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">pushq</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">pqueue_t</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;</span><span class="token plain"> q</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> pqueue_item_t v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">void</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> q</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">push_back</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">push_heap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">q</span><span class="token punctuation"
<p>And now we can finally move to the actual implementation of the Dijkstra&#x27;s
algorithm:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">auto</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">dijkstra</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> graph</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;</span><span class="token plain"> g</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> vertex_t</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;</span><span class="token plain"> source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-&gt;</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">vector</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">vector</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// make sure that source exists</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">assert</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">g</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">has</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// initialize the distances</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">vector</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">std</span><span class="token double-colon punctuation" style="color:hsl(119, 34%, 47%)">::
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="time-complexity">Time complexity<a href="#time-complexity" class="hash-link" aria-label="Direct link to Time complexity" title="Direct link to Time complexity"></a></h2>
<p>The time complexity of Dijkstra&#x27;s algorithm differs based on the backing data
structure.</p>
<p>The original implementation doesn&#x27;t leverage the heap which results in
repetitive <em>look up</em> of the “closest” vertex, hence we get the following
worst-case time complexity in the <em>Bachmann-Landau</em> notation:</p>
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal">Θ</mi><mo stretchy="false">(</mo><mi mathvariant="normal"></mi><mi>V</mi><msup><mi mathvariant="normal"></mi><mn>2</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\Theta(\vert V \vert^2)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em"></span><span class="mord">Θ</span><span class="mopen">(</span><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.22222em">V</span><span class="mord"><span class="mord"></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em"><span style="top:-3.113em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span>
<p>If we turn our attention to the backing data structure, we always want the
“cheapest” vertex, that&#x27;s why we can use the min heap, given that we use
Fibonacci heap we can achieve the following amortized time complexity:</p>
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="script">O</mi><mo stretchy="false">(</mo><mi mathvariant="normal"></mi><mi>E</mi><mi mathvariant="normal"></mi><mo>+</mo><mi mathvariant="normal"></mi><mi>V</mi><mi mathvariant="normal"></mi><mo></mo><mi>log</mi><mo></mo><mrow><mi mathvariant="normal"></mi><mi>V</mi><mi mathvariant="normal"></mi></mrow><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{O}(\vert E \vert + \vert V \vert \cdot \log{\vert V \vert})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord mathcal" style="margin-right:0.02778em">O</span><span class="mopen">(</span><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.05764em">E</span><span class="mord"></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.22222em">V</span><span class="mord"></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin"></span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mop">lo<span style="margin-right:0.01389em">g</span></span><span class="mspace" style="margin-right:0.1667em"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.22222em">V</span><span class="mord"></span></span><span class="mclose">)</span></span></span></span></span>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Fibonacci heap</div><div class="admonitionContent_BuS1"><p>Fibonacci heap is known as the heap that provides <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Θ</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\Theta(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord">Θ</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span> <strong>amortized</strong>
insertion and <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">O</mi><mo stretchy="false">(</mo><mi>log</mi><mo></mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{O}(\log{n})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord mathcal" style="margin-right:0.02778em">O</span><span class="mopen">(</span><span class="mop">lo<span style="margin-right:0.01389em">g</span></span><span class="mspace" style="margin-right:0.1667em"></span><span class="mord"><span class="mord mathnormal">n</span></span><span class="mclose">)</span></span></span></span> <strong>amortized</strong> removal of the top (either
min or max).</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="running-the-dijkstra">Running the Dijkstra<a href="#running-the-dijkstra" class="hash-link" aria-label="Direct link to Running the Dijkstra" title="Direct link to Running the Dijkstra"></a></h2>
<p>Let&#x27;s run our code:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Normal cost: 1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Vortex cost: 5</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Graph:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#############</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#..*.*.**#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">##***.....**#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..########.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#...###...#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#...##.#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#.*.#..#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#D...#....#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">########*.*.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#S..........#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#############</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Finite BF] Cost: 22</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Bellman-Ford] Cost: 22</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Dijkstra] Cost: 22</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>OK, so it seems to be working just fine. Now the question arises:</p>
<blockquote>
<p>What happens when we have negative weights in our graph?</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="busting-the-myth-about-looping-dijkstra">Busting the myth about looping Dijkstra<a href="#busting-the-myth-about-looping-dijkstra" class="hash-link" aria-label="Direct link to Busting the myth about looping Dijkstra" title="Direct link to Busting the myth about looping Dijkstra"></a></h2>
<p>One of the very common misconception about Dijkstra&#x27;s algorithm is that it loops
infinitely when you have negative weights or loops in the graph. Well, if we use
our <em>propelling vortices</em>, not only we have the negative weights, but also the
negative loops. Let&#x27;s run our code! Our first naïve approach was actually
looping:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Normal cost: 1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Vortex cost: -1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Graph:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#############</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#..*.*.**#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">##***.....**#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..########.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#...###...#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#...##.#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#..#.*.#..#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#D...#....#.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">########*.*.#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#S..........#</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">#############</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Finite BF] Cost: -240</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Bellman-Ford] Found a negative loop</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Bellman-Ford] Cost: -240</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[Dijkstra] Cost: 14</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Well, it definitely doesn&#x27;t loop. How much does <code>14</code> make sense is a different
matter.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Variations</div><div class="admonitionContent_BuS1"><p>There are multiple variations of the Dijkstra&#x27;s algorithm. You <strong>can</strong> implement
it in such way that with negative weights or loops it loops infinitely, but it
can be countered. In our case we keep the track of the vertices that already got
a shortest path established via the <code>visited</code>, that&#x27;s how even multiple entries
for one vertex in the heap are not an issue.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a href="#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary"></a></h2>
<p>Now we have an algorithm for finding the shortest path that is faster than our
original naïve brute-force or Bellman-Ford. However we need to keep in mind its
requirement of no negative weights for correct functioning.</p>
<p>You can also see how we used our thought process of figuring out the worst-case
time complexity for the naïve or Bellman-Ford algorithm to improve the original
path-finding algorithms.</p></div><footer class="theme-doc-footer docusaurus-mt-lg"><div class="theme-doc-footer-tags-row row margin-bottom--sm"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/algorithms/tags/cpp/">cpp</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/algorithms/tags/dynamic-programming/">dynamic programming</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/algorithms/tags/greedy/">greedy</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/algorithms/tags/dijkstra/">dijkstra</a></li></ul></div></div><div class="theme-doc-footer-edit-meta-row row"><div class="col"><a href="https://github.com/mfocko/blog/tree/main/algorithms/11-paths/2024-01-01-bf-to-astar/02-dijkstra.md" target="_blank" rel="noopener noreferrer" class="theme-edit-this-page"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_Z9Sw" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col lastUpdated_vwxv"><span class="theme-last-updated">Last updated<!-- --> on <b><time datetime="2024-01-03T00:00:00.000Z">Jan 3, 2024</time></b></span></div></div></footer></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="/algorithms/paths/bf-to-astar/bf/"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">BF</div></a><a class="pagination-nav__link pagination-nav__link--next" href="/algorithms/paths/bf-to-astar/astar/"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">A* algorithm</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#intro" class="table-of-contents__link toc-highlight">Intro</a></li><li><a href="#dijkstras-algorithm" class="table-of-contents__link toc-highlight">Dijkstra&#39;s algorithm</a></li><li><a href="#short-description" class="table-of-contents__link toc-highlight">Short description</a></li><li><a href="#used-techniques" class="table-of-contents__link toc-highlight">Used techniques</a></li><li><a href="#implementation" class="table-of-contents__link toc-highlight">Implementation</a></li><li><a href="#time-complexity" class="table-of-contents__link toc-highlight">Time complexity</a></li><li><a href="#running-the-dijkstra" class="table-of-contents__link toc-highlight">Running the Dijkstra</a></li><li><a href="#busting-the-myth-about-looping-dijkstra" class="table-of-contents__link toc-highlight">Busting the myth about looping Dijkstra</a></li><li><a href="#summary" class="table-of-contents__link toc-highlight">Summary</a></li></ul></div></div></div></div></main></div></div></div><footer class="footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="col footer__col"><div class="footer__title">Git</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://github.com/mfocko" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://gitlab.com/mfocko" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitLab<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="
</body>
</html>