{"id":6962,"date":"2020-06-26T22:33:39","date_gmt":"2020-06-27T05:33:39","guid":{"rendered":"https:\/\/zxi.mytechroad.com\/blog\/?p=6962"},"modified":"2020-06-27T11:09:21","modified_gmt":"2020-06-27T18:09:21","slug":"leetcode-1489-find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree","status":"publish","type":"post","link":"https:\/\/zxi.mytechroad.com\/blog\/graph\/leetcode-1489-find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree\/","title":{"rendered":"\u82b1\u82b1\u9171 LeetCode 1489. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree"},"content":{"rendered":"\n<figure class=\"wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"\u82b1\u82b1\u9171 LeetCode 1489. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree - \u5237\u9898\u627e\u5de5\u4f5c EP338\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/GzPUvV85kBI?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>Given a weighted undirected connected graph with&nbsp;<code>n<\/code>&nbsp;vertices numbered from&nbsp;<code>0<\/code>&nbsp;to&nbsp;<code>n-1<\/code>,&nbsp;and an array&nbsp;<code>edges<\/code>&nbsp;where&nbsp;<code>edges[i] = [from<sub>i<\/sub>, to<sub>i<\/sub>, weight<sub>i<\/sub>]<\/code>&nbsp;represents a bidirectional and weighted edge between nodes&nbsp;<code>from<sub>i<\/sub><\/code>&nbsp;and&nbsp;<code>to<sub>i<\/sub><\/code>. A minimum spanning tree (MST) is a subset of the edges of the graph that connects all vertices without cycles&nbsp;and with the minimum possible total edge weight.<\/p>\n\n\n\n<p>Find&nbsp;<em>all the critical and pseudo-critical edges in the minimum spanning tree (MST) of the given graph<\/em>. An MST edge whose deletion from the graph would cause the MST weight to increase is called a&nbsp;<em>critical edge<\/em>. A&nbsp;<em>pseudo-critical edge<\/em>, on the other hand, is that which can appear in some MSTs but not all.<\/p>\n\n\n\n<p>Note that you can return the indices of the edges in any order.<\/p>\n\n\n\n<p><strong>Example 1:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/assets.leetcode.com\/uploads\/2020\/06\/04\/ex1.png\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input:<\/strong> n = 5, edges = [[0,1,1],[1,2,1],[2,3,2],[0,3,2],[0,4,3],[3,4,3],[1,4,6]]\n<strong>Output:<\/strong> [[0,1],[2,3,4,5]]\n<strong>Explanation:<\/strong> The figure above describes the graph.\nThe following figure shows all the possible MSTs:\n\nNotice that the two edges 0 and 1 appear in all MSTs, therefore they are critical edges, so we return them in the first list of the output.\nThe edges 2, 3, 4, and 5 are only part of some MSTs, therefore they are considered pseudo-critical edges. We add them to the second list of the output.\n<\/pre>\n\n\n\n<p><strong>Example 2:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/assets.leetcode.com\/uploads\/2020\/06\/04\/ex2.png\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input:<\/strong> n = 4, edges = [[0,1,1],[1,2,1],[2,3,1],[0,3,1]]\n<strong>Output:<\/strong> [[],[0,1,2,3]]\n<strong>Explanation:<\/strong> We can observe that since all 4 edges have equal weight, choosing any 3 edges from the given 4 will yield an MST. Therefore all 4 edges are pseudo-critical.\n<\/pre>\n\n\n\n<p><strong>Constraints:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>2 &lt;= n &lt;= 100<\/code><\/li><li><code>1 &lt;= edges.length &lt;= min(200, n * (n - 1) \/ 2)<\/code><\/li><li><code>edges[i].length == 3<\/code><\/li><li><code>0 &lt;= from<sub>i<\/sub>&nbsp;&lt; to<sub>i<\/sub>&nbsp;&lt; n<\/code><\/li><li><code>1 &lt;= weight<sub>i<\/sub>&nbsp;&lt;= 1000<\/code><\/li><li>All pairs&nbsp;<code>(from<sub>i<\/sub>, to<sub>i<\/sub>)<\/code>&nbsp;are distinct.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Solution: Brute Force?<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"540\" src=\"https:\/\/zxi.mytechroad.com\/blog\/wp-content\/uploads\/2020\/06\/1489-ep338.png\" alt=\"\" class=\"wp-image-6967\" srcset=\"https:\/\/zxi.mytechroad.com\/blog\/wp-content\/uploads\/2020\/06\/1489-ep338.png 960w, https:\/\/zxi.mytechroad.com\/blog\/wp-content\/uploads\/2020\/06\/1489-ep338-300x169.png 300w, https:\/\/zxi.mytechroad.com\/blog\/wp-content\/uploads\/2020\/06\/1489-ep338-768x432.png 768w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" \/><\/figure>\n\n\n\n<p>For each edge<br>1. exclude it and build a MST, cost increased =&gt; critical<br>2. for a non critical edge, force include it and build a MST, cost remains the same =&gt; pseudo critical<\/p>\n\n\n\n<p>Proof of 2, if a non critical \/ non pseudo critical edge was added into the MST, the total cost must be increased. So if the cost remains the same, must be the other case. Since we know the edge is non-critical, so it has to be pseudo critical.<\/p>\n\n\n\n<div class=\"responsive-tabs\">\n<h2 class=\"tabtitle\">C++<\/h2>\n<div class=\"tabcontent\">\n\n<pre lang=\"C++\">\n\/\/ Author: Huahua\nclass UnionFind {\n public:\n  explicit UnionFind(int n): p_(n), r_(n) { iota(begin(p_), end(p_), 0); } \/\/ e.g. p[i] = i\n  int Find(int x) { return p_[x] == x ? x : p_[x] = Find(p_[x]); }\n  bool Union(int x, int y) {\n    int rx = Find(x);\n    int ry = Find(y);\n    if (rx == ry) return false;\n    if (r_[rx] == r_[ry]) {\n      p_[rx] = ry;\n      ++r_[ry];\n    } else if (r_[rx] > r_[ry]) {\n      p_[ry] = rx;\n    } else {\n      p_[rx] = ry;\n    }    \n    return true;\n  }\n private:\n  vector<int> p_, r_;  \n};\n\nclass Solution {\npublic:\n  vector<vector<int>> findCriticalAndPseudoCriticalEdges(int n, vector<vector<int>>& edges) {\n    \/\/ Record the original id.\n    for (int i = 0; i < edges.size(); ++i) edges[i].push_back(i);\n    \/\/ Sort edges by weight.\n    sort(begin(edges), end(edges), [&#038;](const auto&#038; e1, const auto&#038; e2){\n      if (e1[2] != e2[2]) return e1[2] < e2[2];        \n      return e1 < e2;\n    });\n    \/\/ Cost of MST, ex: edge to exclude, in: edge to include.\n    auto MST = [&#038;](int ex = -1, int in = -1) -> int {\n      UnionFind uf(n);\n      int cost = 0;\n      int count = 0;\n      if (in >= 0) {\n        cost += edges[in][2];\n        uf.Union(edges[in][0], edges[in][1]);\n        count++;\n      }\n      for (int i = 0; i < edges.size(); ++i) {        \n        if (i == ex) continue;\n        if (!uf.Union(edges[i][0], edges[i][1])) continue;\n        cost += edges[i][2];\n        ++count;\n      }\n      return count == n - 1 ? cost : INT_MAX;\n    };\n    const int min_cost = MST();\n    vector<int> criticals;\n    vector<int> pseudos;\n    for (int i = 0; i < edges.size(); ++i) {\n      \/\/ Cost increased or can't form a tree.\n      if (MST(i) > min_cost) {\n        criticals.push_back(edges[i][3]);\n      } else if (MST(-1, i) == min_cost) {\n        pseudos.push_back(edges[i][3]);\n      }\n    }\n    return {criticals, pseudos};\n  }\n};\n<\/pre>\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Given a weighted undirected connected graph with&nbsp;n&nbsp;vertices numbered from&nbsp;0&nbsp;to&nbsp;n-1,&nbsp;and an array&nbsp;edges&nbsp;where&nbsp;edges[i] = [fromi, toi, weighti]&nbsp;represents a bidirectional and weighted edge between nodes&nbsp;fromi&nbsp;and&nbsp;toi. A minimum spanning&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[76],"tags":[77,217,533,113],"class_list":["post-6962","post","type-post","status-publish","format-standard","hentry","category-graph","tag-graph","tag-hard","tag-mst","tag-union-find","entry","simple"],"_links":{"self":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/6962","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/comments?post=6962"}],"version-history":[{"count":3,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/6962\/revisions"}],"predecessor-version":[{"id":6968,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/6962\/revisions\/6968"}],"wp:attachment":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/media?parent=6962"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/categories?post=6962"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/tags?post=6962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}