A simple Intuitive Solution || Easy to grasp || C++
IntuitionWe have to minimise the bitwise AND of the path from u to v.
Idea : Bitwise AND is a decreasing propery.
So we can include all the edges of a component
# Intuition
We have to minimise the bitwise AND of the path from u to v.
**Idea** : Bitwise AND is a decreasing propery.
So we can include all the edges of a component to minimise the AND.
And thats it. If u and v are in same component then the answer is the bitwise AND of all the edges of that component.Else -1.

# Approach
DfS function will fill the map (ultimate Parent of component -> vector of all nodes of component).

Calculate Bitwise AND of every edges of a component.

The answer of query will be bitwise AND of the component where u and v lie.

# Code
```cpp []
#include <bits/stdc++.h>
using namespace std;

class DisjointSet {
    vector<int64_t> rank, parent, size;

public:
    explicit DisjointSet(int64_t n) {
        rank.resize(n + 1, 0);
        parent.resize(n + 1);
        size.resize(n + 1, 1);
        iota(parent.begin(), parent.end(), 0);
    }

    int64_t findUPar(int64_t node) {
        if (node != parent[node]) {
            parent[node] = findUPar(parent[node]);
        }
        return parent[node];
    }

    void unionByRank(int64_t u, int64_t v) {
        int64_t ulp_u = findUPar(u);
        int64_t ulp_v = findUPar(v);
        if (ulp_u == ulp_v) return;

        if (rank[ulp_u] < rank[ulp_v]) {
            parent[ulp_u] = ulp_v;
        } else if (rank[ulp_v] < rank[ulp_u]) {
            parent[ulp_v] = ulp_u;
        } else {
            parent[ulp_v] = ulp_u;
            rank[ulp_u]++;
        }
    }

    void unionBySize(int64_t u, int64_t v) {
        int64_t ulp_u = findUPar(u);
        int64_t ulp_v = findUPar(v);
        if (ulp_u == ulp_v) return;

        if (size[ulp_u] < size[ulp_v]) {
            parent[ulp_u] = ulp_v;
            size[ulp_v] += size[ulp_u];
        } else {
            parent[ulp_v] = ulp_u;
            size[ulp_u] += size[ulp_v];
        }
    }
};

class Solution {
public:
    vector<int> minimumCost(int n, vector<vector<int>> &edges, vector<vector<int>> &query) {
        vector<vector<pair<int, int>>> adj(n + 1);
        DisjointSet ds(n);

    
        for (int i = 0; i < edges.size(); i++) {
            int u = edges[i][0];
            int v = edges[i][1];
            int w = edges[i][2];
            adj[u].emplace_back(v, w);
            adj[v].emplace_back(u, w);
            ds.unionBySize(u, v);
        }

        map<int, vector<int>> mp;
        map<int, int> mp2;

        int components = 0;
        vector<int> vis(n + 1, 0);

        
        function<void(int, int)> dfs = [&](int node, int cmp) -> void {
            vis[node] = 1;
            mp[cmp].push_back(node);
            for (const auto &it : adj[node]) {
                if (!vis[it.first]) {
                    dfs(it.first, cmp);
                }
            }
        };

        
        for (int i = 1; i <= n; i++) {
            if (!vis[i]) {
                components = ds.findUPar(i);
                dfs(i, components);
            }
        }

        for (auto &[cmp, vec] : mp) {
            vector<int> tp;
            for (auto &node : vec) {
                for (auto &it : adj[node]) {
                    tp.push_back(it.second);
                }
            }

            
            int ans = (tp.empty()) ? -1 : tp[0];
            for (int i = 1; i < tp.size(); i++) {
                ans &= tp[i];
            }
            mp2[cmp] = ans;
        }

        int m = query.size();
        vector<int> ans(m);

        for (int i = 0; i < m; i++) {
            int u = query[i][0];
            int v = query[i][1];
            
            if (ds.findUPar(v) != ds.findUPar(u)) {
                ans[i] = -1;
            } else {
                ans[i] = mp2[ds.findUPar(u)];
            }
        }

        return ans;
    }
};

```
['Array', 'Bit Manipulation', 'Union Find', 'Graph', 'C++']