{"id":15706382,"url":"https://github.com/kimwnasptd/mst-cartesian-trees","last_synced_at":"2025-05-12T18:54:47.411Z","repository":{"id":145544639,"uuid":"117135000","full_name":"kimwnasptd/MST-Cartesian-Trees","owner":"kimwnasptd","description":"An implementation of creating a Cartesian Tree from an MST","archived":false,"fork":false,"pushed_at":"2018-01-11T19:13:55.000Z","size":9,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-01T01:45:05.348Z","etag":null,"topics":["algorithms","cartesian-tree","minimum-spanning-trees"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kimwnasptd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-11T18:07:46.000Z","updated_at":"2023-02-10T18:47:26.000Z","dependencies_parsed_at":"2023-04-28T14:48:34.738Z","dependency_job_id":null,"html_url":"https://github.com/kimwnasptd/MST-Cartesian-Trees","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kimwnasptd%2FMST-Cartesian-Trees","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kimwnasptd%2FMST-Cartesian-Trees/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kimwnasptd%2FMST-Cartesian-Trees/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kimwnasptd%2FMST-Cartesian-Trees/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kimwnasptd","download_url":"https://codeload.github.com/kimwnasptd/MST-Cartesian-Trees/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253804551,"owners_count":21967049,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","cartesian-tree","minimum-spanning-trees"],"created_at":"2024-10-03T20:22:31.327Z","updated_at":"2025-05-12T18:54:47.389Z","avatar_url":"https://github.com/kimwnasptd.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MST-Cartesian-Trees\nThe other day in my CS Classes they gave us an assignment where given a graph with edges\nand weights, we had to answer a range of queries for the Minimax Path Problem. The number of\nqueries was ~ 100.000 and the Graph could have up to V=30.000 Nodes. This means that a naive\nimplementation of just finding an MST and then with a modified DFS to calculate the minimax\ndistance between all the pairs wouldn't do the job since it would have O(V^2) complexity.\n\n# On to Cartesian Trees\nThe most efficient solution for the problem would be to create a Cartesian Tree based from\nthe Minumum Spanning Tree which allows us to find the minimax distance between any pair of \nvertices to be queried in constant time per query, using lowest common ancestor queries in \na Cartesian tree.\n\nThe only problem was that both Wikipedia and and some papers I found olnline with a basic \nGoogle Search described an Algorithm for creating the Cartesian with O(n) complexity but\nby using a Structure for keeping track of decremental components of a tree. For this struct\nthere was of course no code available and only one paper describing it. So I had to tackle\nthe creation of the Cartesian with a different way, given that there were just two days remaining\nfor the assignment. \n\nIn the end, I came up with a way to create the Cartesian Tree from the MST with an O(nlogn) \ncomplexity, which was pretty acceptable given that I had to do Kruskal in order to find the\nactual MST. So in this repo I give the code of the full assignment which includes both the \ncode for creating the Cartesian Tree, but also the code for transforming the LCA to RMQ for \nactually answering the queries.\n\nBellow I'll give a basic explanation of the algorithm used to create the Cartesian Tree.\n\n# Creating the Cartesian Tree\nTo do this instead of creating the tree top-down we will create it Bottom-Up. We will be \nconstantly changing the parents of the current nodes and keep creating the tree until we\nget to the top. The top Node will be the node V + E (where E = V - 1) and it's value will\nbe the weight of the heaviest edge and the leaves will be the Nodes of the initial Graph. \nThe resulting tree will be stored in an array of length V+E where each element is a type\nCartesianNode Class which keeps track of its parent Node, as well as its children.\n\nFirstly we will need a struct that can keep track of the parents of the nodes that we will\nbe changing. For this we will use a Union-Find Struct (hence the O(nlogn) complexity) but \nwill a minor modification for keeping track of the parent Nodes.\n\n\nWith this, we will loop for each edge in sorted edges (with increasing order based on their \nweights) of the MST. In each iteration we will add another edge as a Node in the tree and\nupdate the values of that node (its children) as well as its children (change the value of\ntheir parent). \n\n# Answering the Queries\nI won't get into the technical details here, since there is this [tons of helpful](https://www.topcoder.com/community/data-science/data-science-tutorials/range-minimum-query-and-lowest-common-ancestor/)\nexplanation of the procedure from here on. The general idea is that from this Cartesian \ntree we can find the minimax shortest path by finding the Lowest Common Ancestor in the \nCartesian Tree for the two Nodes. But, finding an LCA is equivalent with an RMQ and since\nby doing a O(nlogn) preprocess we can then answer in O(1) any RMQ, we can finaly also \nanswer any query of the initial problem in constant time.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkimwnasptd%2Fmst-cartesian-trees","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkimwnasptd%2Fmst-cartesian-trees","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkimwnasptd%2Fmst-cartesian-trees/lists"}