Kotlin || Union Find || Beats 100%
Intuition
Bitwise AND Property: When performing a bitwise AND operation on multiple values, the result can only decrease or remain the same. This means that if
# Intuition
1. **Bitwise AND Property:** When performing a bitwise AND operation on multiple values, the result can only decrease or remain the same. This means that if we traverse all possible edges in a connected component, the minimum cost is the bitwise AND of all edges in that component.
2. **Connected Components Matter:** If two nodes belong to the same connected component, there exists a walk between them. Otherwise, the answer is -1 since no path exists.
3. **Efficiently Finding Components:** To determine which nodes are in the same connected component, we use Disjoint Set Union (DSU), also known as Union-Find.

# Approach
**Step 1: Union-Find to Identify Components**
- We use the Union-Find data structure to efficiently determine connected components.
- Each node starts as its own representative.
- We iterate through the edges and merge nodes that are directly connected.

**Step 2: Compute Minimum AND Cost per Component**
- For each connected component, compute the AND of all edge weights.
- Store this minimum AND cost per component.

**Step 3: Answer Queries in Constant Time**
- For each query (si, ti), check if si and ti belong to the same component.
- If they do, return the precomputed minimum cost for that component.
- Otherwise, return -1.

# Complexity
- Time complexity:
<!-- Add your time complexity here, e.g. $$O(n)$$ -->

- Space complexity:
<!-- Add your space complexity here, e.g. $$O(n)$$ -->

# Code
```kotlin []
class Solution {
    fun minimumCost(n: Int, edges: Array<IntArray>, query: Array<IntArray>): IntArray {
        val representative = IntArray(n) { 0 }
        for (i in 0..<n) {
            representative[i] = i
        }

        fun findRepresentative(u: Int): Int {
            if (representative[u] == u) {
                return u
            }
            representative[u] = findRepresentative(representative[u])
            return representative[u]
        }

        fun union(u: Int, v: Int) {
            val a = findRepresentative(u)
            val b = findRepresentative(v)
            if (a != b) {
                representative[a] = b
            }
        }

        for (e in edges) {
            union(e[0], e[1])
        }

        val costs = IntArray(n) { -1 }
        for (e in edges) {
            val r = findRepresentative(e[0])
            if (costs[r] == -1) {
                costs[r] = e[2]
            } else {
                costs[r] = costs[r] and e[2]
            }
        }

        val ans = IntArray(query.size) { -1 }
        for ((i, q) in query.withIndex()) {
            val a = findRepresentative(q[0])
            val b = findRepresentative(q[1])
            if (a == b) {
                ans[i] = costs[a]
            }
        }
        return ans
    }
}
```
['Bit Manipulation', 'Union Find', 'Kotlin']