Minimum Cost Walk in Weighted Graph - Union Find [JS]

Description 

Solution: Union Find

It's optimal to visit as many edges as possible to lower the total bitwise AND.
Because we can visit nodes and edges more than once, nodes within the same connected component can take the total bitwise AND of ALL edges within that connected component.
Any pair of nodes within the same connected component will have the same cost.

Use union find to get the connected groups and find the bitwise AND cost for the group.
Note: If the two nodes of the query are equal, the answer is 0 because we are already at the target.

n = number of nodesm = number of edgesk = number of queries
Time Complexity: O(n + m + q)
Space Complexity: O(n + m + q)

var minimumCost = function(n, edges, query) {
  let uf = new UnionFind(n), weights = Array(n).fill(-1);
  for (let [u, v, weight] of edges) {
    uf.union(u, v);
    weights[u] = weights[u] === -1 ? weight : weights[u] & weight; // only need to keep track of edges from u -> v and not v -> u because they will be part of the same connected component and will be duplicated
  }
  let groupCost = {};
  for (let i = 0; i < n; i++) {
    let parent = uf.find(i);
    groupCost[parent] = groupCost[parent] === undefined ? weights[i] : groupCost[parent] & weights[i];
  }
  let ans = [];
  for (let [s, t] of query) {
    if (!uf.isConnected(s, t)) ans.push(-1);
    else if (s === t) ans.push(0);
    else ans.push(groupCost[uf.find(s)]);
  }
  return ans;
};

class UnionFind {
  constructor(size) {
    this.root = Array(size);
    this.rank = Array(size);
    this.size = size;
    for (let i = 0; i < size; i++) {
      this.root[i] = i;
      this.rank[i] = 1;
    }
  }
  find(x) {
    if (this.root[x] === x) return x;
    return this.root[x] = this.find(this.root[x]);
  }
  union(x, y) {
    let rootX = this.find(x);
    let rootY = this.find(y);
    if (rootX === rootY) return false;
    if (this.rank[rootX] > this.rank[rootY]) {
      this.root[rootY] = rootX;
    } else if (this.rank[rootX] < this.rank[rootY]) {
      this.root[rootX] = rootY;
    } else {
      this.root[rootY] = rootX;
      this.rank[rootX]++;
    }
    this.size--;
    return true;
  }
  isConnected(x, y) {
    return this.find(x) === this.find(y);
  }
}

Comments

Popular posts from this blog

Maximum Value of an Ordered Triplet II - Two Solutions [JS]

Maximum Sum of Distinct Subarrays With Length K - Sliding Window w/ Two Pointers & Set [JS]

Sum of Prefix Scores of Strings - Trie [JS]

Maximum Count of Positive Integer and Negative Integer - Binary Search [JS]

Count Subarrays With Median K - Count Left & Right Balance [JS]