|
6619 | 6619 | <ulclass="metadata page-metadata"data-bi-name="page info"lang="en-us"dir="ltr">
|
6620 | 6620 |
|
6621 | 6621 | Last update:
|
6622 |
| -<spanclass="git-revision-date-localized-plugin git-revision-date-localized-plugin-date"title="April15, 2025 02:32:08">April15, 2025</span>  |
| 6622 | +<spanclass="git-revision-date-localized-plugin git-revision-date-localized-plugin-date"title="April22, 2025 02:11:52">April22, 2025</span>  |
6623 | 6623 |
|
6624 | 6624 | <!-- Tags -->
|
6625 | 6625 |
|
@@ -6687,27 +6687,31 @@ <h2 id="rotating-the-points-and-chebyshev-distance">Rotating the points and Cheb
|
6687 | 6687 | <h2id="manhattan-minimum-spanning-tree">Manhattan Minimum Spanning Tree<aclass="headerlink"href="#manhattan-minimum-spanning-tree"title="Permanent link">¶</a></h2>
|
6688 | 6688 | <p>The Manhattan MST problem consists of, given some points in the plane, find the edges that connect all the points and have a minimum total sum of weights. The weight of an edge that connects two points is their Manhattan distance. For simplicity, we assume that all points have different locations.
|
6689 | 6689 | Here we show a way of finding the MST in<spanclass="arithmatex">$O(n \log{n})$</span> by finding for each point its nearest neighbor in each octant, as represented by the image below. This will give us<spanclass="arithmatex">$O(n)$</span> candidate edges, which, as we show below, will guarantee that they contain the MST. The final step is then using some standard MST, for example,<ahref="https://cp-algorithms.com/graph/mst_kruskal_with_dsu.html">Kruskal algorithm using disjoint set union</a>.</p>
|
6690 |
| -<center> |
6691 |
| - |
6692 |
| -*The 8 octants relative to a point S*</center> |
| 6690 | +<divstyle="text-align: center;"> |
| 6691 | +<imgsrc="manhattan-mst-octants.png"alt="8 octants picture"> |
| 6692 | + *The 8 octants relative to a point S* |
| 6693 | +</div> |
6693 | 6694 |
|
6694 | 6695 | <p>The algorithm shown here was first presented in a paper from<ahref="https://ieeexplore.ieee.org/document/913303">H. Zhou, N. Shenoy, and W. Nichollos (2002)</a>. There is also another know algorithm that uses a Divide and conquer approach by<ahref="https://www.academia.edu/15667173/On_computing_all_north_east_nearest_neighbors_in_the_L1_metric">J. Stolfi</a>, which is also very interesting and only differ in the way they find the nearest neighbor in each octant. They both have the same complexity, but the one presented here is easier to implement and has a lower constant factor.</p>
|
6695 | 6696 | <p>First, let's understand why it is enough to consider only the nearest neighbor in each octant. The idea is to show that for a point<spanclass="arithmatex">$s$</span> and any two other points<spanclass="arithmatex">$p$</span> and<spanclass="arithmatex">$q$</span> in the same octant,<spanclass="arithmatex">$d(p, q) < \max(d(s, p), d(s, q))$</span>. This is important, because it shows that if there was a MST where<spanclass="arithmatex">$s$</span> is connected to both<spanclass="arithmatex">$p$</span> and<spanclass="arithmatex">$q$</span>, we could erase one of these edges and add the edge<spanclass="arithmatex">$(p,q)$</span>, which would decrease the total cost. To prove this, we assume without loss of generality that<spanclass="arithmatex">$p$</span> and<spanclass="arithmatex">$q$</span> are in the octanct<spanclass="arithmatex">$R_1$</span>, which is defined by:<spanclass="arithmatex">$x_s \leq x$</span> and<spanclass="arithmatex">$x_s - y_s > x - y$</span>, and then do some casework. The image below give some intuition on why this is true.</p>
|
6696 |
| -<center> |
6697 |
| - |
6698 |
| -*Intuitively, the limitation of the octant makes it impossible that $p$ and $q$ are both closer to $s$ than to each other*</center> |
| 6697 | +<divstyle="text-align: center;"> |
| 6698 | +<imgsrc="manhattan-mst-uniqueness.png"alt="unique nearest neighbor"> |
| 6699 | + *Intuitively, the limitation of the octant makes it impossible that $p$ and $q$ are both closer to $s$ than to each other* |
| 6700 | +</div> |
6699 | 6701 |
|
6700 | 6702 | <p>Therefore, the main question is how to find the nearest neighbor in each octant for every single of the<spanclass="arithmatex">$n$</span> points.</p>
|
6701 | 6703 | <h2id="nearest-neighbor-in-each-octant-in-on-log-n">Nearest Neighbor in each Octant in O(n log n)<aclass="headerlink"href="#nearest-neighbor-in-each-octant-in-on-log-n"title="Permanent link">¶</a></h2>
|
6702 | 6704 | <p>For simplicity we focus on the NNE octant (<spanclass="arithmatex">$R_1$</span> in the image above). All other directions can be found with the same algorithm by rotating the input.</p>
|
6703 | 6705 | <p>We will use a sweep-line approach. We process the points from south-west to north-east, that is, by non-decreasing<spanclass="arithmatex">$x + y$</span>. We also keep a set of points which don't have their nearest neighbor yet, which we call "active set". We add the images below to help visualize the algorithm.</p>
|
6704 |
| -<center> |
6705 |
| - |
6706 |
| -*In black with an arrow you can see the direction of the line-sweep. All the points below this lines are in the active set, and the points above are still not processed. In green we see the points which are in the octant of the processed point. In red the points that are not in the searched octant.*</center> |
6707 |
| - |
6708 |
| -<center> |
| 6706 | +<divstyle="text-align: center;"> |
| 6707 | +<imgsrc="manhattan-mst-sweep-line-1.png"alt="manhattan-mst-sweep"> |
| 6708 | + *In black with an arrow you can see the direction of the line-sweep. All the points below this lines are in the active set, and the points above are still not processed. In green we see the points which are in the octant of the processed point. In red the points that are not in the searched octant.* |
| 6709 | +</div> |
6709 | 6710 |
|
6710 |
| -*In this image we see the active set after processing the point $p$. Note that the $2$ green points of the previous image had $p$ in its north-north-east octant and are not in the active set anymore, because they already found their nearest neighbor.*</center> |
| 6711 | +<divstyle="text-align: center;"> |
| 6712 | +<imgsrc="manhattan-mst-sweep-line-2.png"alt="manhattan-mst-sweep"> |
| 6713 | + *In this image we see the active set after processing the point $p$. Note that the $2$ green points of the previous image had $p$ in its north-north-east octant and are not in the active set anymore, because they already found their nearest neighbor.* |
| 6714 | +</div> |
6711 | 6715 |
|
6712 | 6716 | <p>When we add a new point point<spanclass="arithmatex">$p$</span>, for every point<spanclass="arithmatex">$s$</span> that has it in its octant we can safely assign<spanclass="arithmatex">$p$</span> as the nearest neighbor. This is true because their distance is<spanclass="arithmatex">$d(p,s) = |x_p - x_s| + |y_p - y_s| = (x_p + y_p) - (x_s + y_s)$</span>, because<spanclass="arithmatex">$p$</span> is in the north-north-east octant. As all the next points will not have a smaller value of<spanclass="arithmatex">$x + y$</span> because of the sorting step,<spanclass="arithmatex">$p$</span> is guaranteed to have the smaller distance. We can then remove all such points from the active set, and finally add<spanclass="arithmatex">$p$</span> to the active set.</p>
|
6713 | 6717 | <p>The next question is how to efficiently find which points<spanclass="arithmatex">$s$</span> have<spanclass="arithmatex">$p$</span> in the north-north-east octant. That is, which points<spanclass="arithmatex">$s$</span> satisfy:</p>
|
@@ -6773,7 +6777,7 @@ <h2 id="problems">Problems<a class="headerlink" href="#problems" title="Permanen
|
6773 | 6777 |
|
6774 | 6778 | <ulclass="metadata page-metadata"data-bi-name="page info"lang="en-us"dir="ltr">
|
6775 | 6779 | <spanclass="contributors-text">Contributors:</span>
|
6776 |
| -<ulclass="contributors"data-bi-name="contributors"><li><ahref="https://github.com/NaimSS"title="NaimSS"data-bi-name="contributorprofile"target="_blank">NaimSS</a> (80.0%)</li><li><ahref="https://github.com/gabsrp2002"title="gabsrp2002"data-bi-name="contributorprofile"target="_blank">gabsrp2002</a> (11.89%)</li><li><ahref="https://github.com/izanbf1803"title="izanbf1803"data-bi-name="contributorprofile"target="_blank">izanbf1803</a> (3.78%)</li><li><ahref="https://github.com/mhayter"title="mhayter"data-bi-name="contributorprofile"target="_blank">mhayter</a> (3.24%)</li><li><ahref="https://github.com/adamant-pwn"title="adamant-pwn"data-bi-name="contributorprofile"target="_blank">adamant-pwn</a> (1.08%)</li></ul> |
| 6780 | +<ulclass="contributors"data-bi-name="contributors"><li><ahref="https://github.com/NaimSS"title="NaimSS"data-bi-name="contributorprofile"target="_blank">NaimSS</a> (71.95%)</li><li><ahref="https://github.com/mhayter"title="mhayter"data-bi-name="contributorprofile"target="_blank">mhayter</a> (11.64%)</li><li><ahref="https://github.com/gabsrp2002"title="gabsrp2002"data-bi-name="contributorprofile"target="_blank">gabsrp2002</a> (11.64%)</li><li><ahref="https://github.com/izanbf1803"title="izanbf1803"data-bi-name="contributorprofile"target="_blank">izanbf1803</a> (3.7%)</li><li><ahref="https://github.com/adamant-pwn"title="adamant-pwn"data-bi-name="contributorprofile"target="_blank">adamant-pwn</a> (1.06%)</li></ul> |
6777 | 6781 | </ul>
|
6778 | 6782 |
|
6779 | 6783 | </article>
|
|