Medium solution
Intuition
Bitwise AND either decreases the value or keeps as it is, which means using every possible road gives the minimum cost.
If there is no way connected b
# Intuition
<!-- Describe your first thoughts on how to solve this problem. -->
- Bitwise AND either decreases the value or keeps as it is, which means using every possible road gives the minimum cost.
- If there is no way connected between `node1` and `node2`, then it is `-1`
# Approach
<!-- Describe your approach to solving the problem. -->
### 1. **Initialize DSU:**  
   - Create `arr[n]` (parent/size) and `val[n]` (minimum AND in each component), both initialized to `-1`.  

### 2. **Process Edges:**  
   - For each edge `(a, b, weight)`:  
     1. Find roots of `a` and `b` using path compression.  
     2. Compute `bitwise AND` of `weight` with `val[root]` if already set.  
     3. Merge smaller component into larger (union by size) and update `val[]`.  

### 3. **Process Queries:**  
   - For each query `(a, b)`:  
     1. Find the roots of `a` and `b`.  
     2. If they share the same root, return `val[root]`; otherwise, return `-1`.  

### 4. **Return the results for all queries.**
# Complexity
- Time complexity:
<!-- Add your time complexity here, e.g. $$O(n)$$ -->
$$O(n)$$
- Space complexity:
<!-- Add your space complexity here, e.g. $$O(n)$$ -->
$$O(n)$$
# Code
```cpp []
class Solution {
public:
    vector<int> minimumCost(int n, vector<vector<int>>& edges, vector<vector<int>>& query) {
        vector<int> arr(n, -1);
        vector<int> val(n, -1);
        for(auto edge: edges) {
            int a = edge[0];
            int b = edge[1];
            while(arr[a] >= 0) a = arr[a];
            while(arr[b] >= 0) b = arr[b];

            int bit = edge[2];
            if(val[a] != -1) bit &= val[a];
            if(val[b] != -1) bit &= val[b];

            if(a == b) {
                val[a] = bit;
            } else if(arr[a] <= arr[b]) {
                arr[a] += arr[b];
                arr[b] = a;
                val[a] = bit;
            } else {
                arr[b] += arr[a];
                arr[a] = b;
                val[b] = bit;
            }
        }

        vector<int> res;
        for(auto list: query) {
            int a = list[0];
            int b = list[1];
            while(arr[a] >= 0) a = arr[a];
            while(arr[b] >= 0) b = arr[b];
            if(a==b)
                res.push_back(val[a]);
            else 
                res.push_back(-1);
        }
        return res;
        
    }
};
```
```c []
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* minimumCost(int n, int** edges, int edgesSize, int* edgesColSize, int** query, int querySize, int* queryColSize, int* returnSize) {
    int* arr = (int*)calloc(n, sizeof(int));
    int* val = (int*)calloc(n, sizeof(int));
    for(int i=0; i<n; i++) {
        arr[i] = -1;
        val[i] = -1;
    }
    for(int i=0; i<edgesSize; i++) {
        int a = edges[i][0];
        int b = edges[i][1];
        while(arr[a] >= 0) a = arr[a];
        while(arr[b] >= 0) b = arr[b];

        int bit = edges[i][2];
        if(val[a] != -1) bit &= val[a];
        if(val[b] != -1) bit &= val[b];

        if(a == b) {
            val[a] = bit;
        } else if(arr[a] <= arr[b]) {
            arr[a] += arr[b];
            arr[b] = a;
            val[a] = bit;
        } else {
            arr[b] += arr[a];
            arr[a] = b;
            val[b] = bit;
        }
    }

    int* res = (int*)calloc(querySize, sizeof(int));
    for(int i=0; i<querySize; i++) {
        int a = query[i][0];
        int b = query[i][1];
        while(arr[a] >= 0) a = arr[a];
        while(arr[b] >= 0) b = arr[b];
        if(a==b)
            res[i] = val[a];
        else 
            res[i] = -1;
    }
    *returnSize = querySize;
    return res;
}
```
```java []
class Solution {
    public int[] minimumCost(int n, int[][] edges, int[][] query) {
        int[] arr = IntStream.generate(() -> -1).limit(n).toArray();
        int[] val = IntStream.generate(() -> -1).limit(n).toArray();
        for(int[] edge: edges) {
            int a = edge[0];
            int b = edge[1];
            while(arr[a] >= 0) a = arr[a];
            while(arr[b] >= 0) b = arr[b];

            int bit = edge[2];
            if(val[a] != -1) bit &= val[a];
            if(val[b] != -1) bit &= val[b];

            if(a == b) {
                val[a] = bit;
            } else if(arr[a] <= arr[b]) {
                arr[a] += arr[b];
                arr[b] = a;
                val[a] = bit;
            } else {
                arr[b] += arr[a];
                arr[a] = b;
                val[b] = bit;
            }
        }

        int[] res = new int[query.length];
        for(int i=0; i<query.length; i++) {
            int a = query[i][0];
            int b = query[i][1];
            while(arr[a] >= 0) a = arr[a];
            while(arr[b] >= 0) b = arr[b];
            if(a==b)
                res[i] = val[a];
            else 
                res[i] = -1;
        }
        return res;
    }
}
```
```javascript []
/**
 * @param {number} n
 * @param {number[][]} edges
 * @param {number[][]} query
 * @return {number[]}
 */
var minimumCost = function(n, edges, query) {
    let arr = new Array(n).fill(-1);
    let val = new Array(n).fill(-1);
    for(let edge of edges) {
        let a = edge[0];
        let b = edge[1];
        while(arr[a] >= 0) a = arr[a];
        while(arr[b] >= 0) b = arr[b];

        let bit = edge[2];
        if(val[a] != -1) bit &= val[a];
        if(val[b] != -1) bit &= val[b];

        if(a == b) {
            val[a] = bit;
        } else if(arr[a] <= arr[b]) {
            arr[a] += arr[b];
            arr[b] = a;
            val[a] = bit;
        } else {
            arr[b] += arr[a];
            arr[a] = b;
            val[b] = bit;
        }
    }

    let res = [];
    for(let list of query) {
        let a = list[0];
        let b = list[1];
        while(arr[a] >= 0) a = arr[a];
        while(arr[b] >= 0) b = arr[b];
        if(a==b)
            res.push(val[a]);
        else 
            res.push(-1);
    }
    return res;
};
```
```python3 []
class Solution:
    def minimumCost(self, n: int, edges: List[List[int]], query: List[List[int]]) -> List[int]:
        arr, val = [-1]*n, [-1]*n
        for edge in edges:
            a = edge[0]
            b = edge[1]
            while arr[a] >= 0: a = arr[a]
            while arr[b] >= 0: b = arr[b]

            bit = edge[2]
            if val[a] != -1: bit &= val[a]
            if val[b] != -1: bit &= val[b]

            if a == b:
                val[a] = bit
            elif arr[a] <= arr[b]:
                arr[a] += arr[b]
                arr[b] = a
                val[a] = bit
            else:
                arr[b] += arr[a]
                arr[a] = b
                val[b] = bit
            
        

        res = []
        for List in query:
            a = List[0]
            b = List[1]
            while arr[a] >= 0: a = arr[a]
            while arr[b] >= 0: b = arr[b]
            if a==b:
                res.append(val[a])
            else:
                res.append(-1)
        
        return res
```
['Array', 'Union Find', 'Graph', 'C', 'C++', 'Java', 'Python3', 'JavaScript']