2023-08-19 Daily Challenge

Today I have done leetcode's August LeetCoding Challenge with cpp.

August LeetCoding Challenge 19

Description

Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree

Given a weighted undirected connected graph with n vertices numbered from 0 to n - 1, and an array edges where edges[i] = [ai, bi, weighti] represents a bidirectional and weighted edge between nodes ai and bi. A minimum spanning tree (MST) is a subset of the graph's edges that connects all vertices without cycles and with the minimum possible total edge weight.

Find all the critical and pseudo-critical edges in the given graph's minimum spanning tree (MST). An MST edge whose deletion from the graph would cause the MST weight to increase is called a critical edge. On the other hand, a pseudo-critical edge is that which can appear in some MSTs but not all.

Note that you can return the indices of the edges in any order.

 

Example 1:

Input: n = 5, edges = [[0,1,1],[1,2,1],[2,3,2],[0,3,2],[0,4,3],[3,4,3],[1,4,6]]
Output: [[0,1],[2,3,4,5]]
Explanation: The figure above describes the graph.
The following figure shows all the possible MSTs:

Notice 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.
The 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.

Example 2:

Input: n = 4, edges = [[0,1,1],[1,2,1],[2,3,1],[0,3,1]]
Output: [[],[0,1,2,3]]
Explanation: 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.

 

Constraints:

  • 2 <= n <= 100
  • 1 <= edges.length <= min(200, n * (n - 1) / 2)
  • edges[i].length == 3
  • 0 <= ai < bi < n
  • 1 <= weighti <= 1000
  • All pairs (ai, bi) are distinct.

Solution

struct UnionSet {
  vector<int> parent;
public:
  UnionSet(int size): parent(size) {
    for(int i = 0; i < size; ++i) {
      parent[i] = i;
    }
  }

  int find(int x) {
    if(parent[x] != x) parent[x] = find(parent[x]);
    return parent[x];
  }

  void merge(int x, int y) {
    x = find(x);
    y = find(y);
    parent[x] = y;
  }
};

class Solution {
  int findMST(
    const vector<vector<int>>& edges,
    int n,
    int ignore,
    int mustHave
  ) {
    UnionSet us(n);

    int weight = 0;
    if(mustHave != -1) {
      us.merge(edges[mustHave][0], edges[mustHave][1]);
      weight += edges[mustHave][2];
    }

    for(int i = 0; i < edges.size(); ++i) {
      if(i == ignore) continue;
      if(us.find(edges[i][0]) == us.find(edges[i][1])) continue;
      us.merge(edges[i][0], edges[i][1]);
      weight += edges[i][2];
    }

    for(int i = 0; i < n; ++i) {
      if(us.find(i) != us.find(0)) {
        weight = INT_MAX;
        continue;
      }
    }

    return weight;
  }
public:
  vector<vector<int>> findCriticalAndPseudoCriticalEdges(int n, vector<vector<int>>& edges) {
    vector<int> critical, pseudoCritical;

    for(int i = 0; i < edges.size(); ++i) {
      edges[i].push_back(i);
    }
    sort(edges.begin(), edges.end(), [](const vector<int> &a, const vector<int> &b) {
      return a[2] < b[2];
    });

    int MSTWeight = findMST(edges, n, -1, -1);

    for(int i = 0; i < edges.size(); ++i) {
      if(MSTWeight < findMST(edges, n, i, -1)) {
        critical.push_back(edges[i][3]);
      } else if(MSTWeight == findMST(edges, n, -1, i)) {
        pseudoCritical.push_back(edges[i][3]);
      }
    }

    return {critical, pseudoCritical};
  }
};

// Accepted
// 66/66 cases passed (160 ms)
// Your runtime beats 58.42 % of cpp submissions
// Your memory usage beats 86.58 % of cpp submissions (14.8 MB)