Minimum Cost Walk in Weighted Graph

hard graph union find bitwise

Problem

An undirected graph has weighted edges [u, v, w]. The cost of a walk is the bitwise AND of the weights of all edges traversed (edges may be repeated, and each repeat is counted). For each query [s, t], return the minimum walk cost from s to t, or −1 if they are not connected.

Because ANDing in more edges can only clear bits, the cheapest walk uses every edge of the component: the answer is the AND of all edge weights inside the connected component shared by s and t.

Inputn = 5, edges = [[0,1,7],[0,1,15],[1,2,6],[1,2,1]], queries = [[1,2],[0,3]]
Output[0, -1]
Component {0,1,2} AND = 7&15&6&1 = 0, so query (1,2) → 0. Node 3 is isolated, so (0,3) → −1.

def min_cost_walk(n, edges, query):
    parent = list(range(n))
    cost = [-1] * n  # AND of all edge weights in the component (all bits set initially)
    for i in range(n):
        cost[i] = -1  # -1 = all bits 1 in two's complement
    def find(x):
        while parent[x] != x:
            parent[x] = parent[parent[x]]
            x = parent[x]
        return x
    for u, v, w in edges:
        ru, rv = find(u), find(v)
        if ru != rv:
            parent[ru] = rv
            cost[rv] &= cost[ru]
        cost[find(u)] &= w
    ans = []
    for s, t in query:
        if s == t:
            ans.append(0)
        elif find(s) != find(t):
            ans.append(-1)
        else:
            ans.append(cost[find(s)])
    return ans
function minCostWalk(n, edges, query) {
  const parent = Array.from({ length: n }, (_, i) => i);
  const cost = new Array(n).fill(-1); // -1 = all bits set
  function find(x) {
    while (parent[x] !== x) { parent[x] = parent[parent[x]]; x = parent[x]; }
    return x;
  }
  for (const [u, v, w] of edges) {
    const ru = find(u), rv = find(v);
    if (ru !== rv) { parent[ru] = rv; cost[rv] &= cost[ru]; }
    cost[find(u)] &= w;
  }
  return query.map(([s, t]) => {
    if (s === t) return 0;
    if (find(s) !== find(t)) return -1;
    return cost[find(s)];
  });
}
class Solution {
    int[] parent;
    int find(int x) {
        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }
        return x;
    }
    public int[] minimumCost(int n, int[][] edges, int[][] query) {
        parent = new int[n];
        int[] cost = new int[n];
        for (int i = 0; i < n; i++) { parent[i] = i; cost[i] = -1; }
        for (int[] e : edges) {
            int ru = find(e[0]), rv = find(e[1]);
            if (ru != rv) { parent[ru] = rv; cost[rv] &= cost[ru]; }
            cost[find(e[0])] &= e[2];
        }
        int[] ans = new int[query.length];
        for (int i = 0; i < query.length; i++) {
            int s = query[i][0], t = query[i][1];
            if (s == t) ans[i] = 0;
            else if (find(s) != find(t)) ans[i] = -1;
            else ans[i] = cost[find(s)];
        }
        return ans;
    }
}
class Solution {
public:
    vector<int> parent;
    int find(int x) {
        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }
        return x;
    }
    vector<int> minimumCost(int n, vector<vector<int>>& edges, vector<vector<int>>& query) {
        parent.resize(n);
        vector<int> cost(n, -1);
        for (int i = 0; i < n; i++) parent[i] = i;
        for (auto& e : edges) {
            int ru = find(e[0]), rv = find(e[1]);
            if (ru != rv) { parent[ru] = rv; cost[rv] &= cost[ru]; }
            cost[find(e[0])] &= e[2];
        }
        vector<int> ans;
        for (auto& q : query) {
            int s = q[0], t = q[1];
            if (s == t) ans.push_back(0);
            else if (find(s) != find(t)) ans.push_back(-1);
            else ans.push_back(cost[find(s)]);
        }
        return ans;
    }
};
Time: O((E + Q) · α(n)) Space: O(n)