Classic Disjoint Set Union kind of problem.
IntuitionApproachComplexity
Time complexity:

Space complexity:
Code
# Intuition
<!-- Describe your first thoughts on how to solve this problem. -->
    If we have to calculate the AND of the paths travelled, then we 
    can use this property of AND "The more numbers you AND, the 
    smaller results you'll get". 
    So how about we keep a dsu which stores the bitwise AND of the 
    entire elements present in a connected graph.
# Approach
<!-- Describe your approach to solving the problem. -->
    Using DSU to make unions and to store the bitwise ANDs of the
    connected components. Then simply return -1 if the two nodes
    does not share a common parent(they are not connected) or the
    value stored in a vector in dsu at any one of the two nodes.
# 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 []
#define INCL()                                                                 \
    ios_base::sync_with_stdio(0);                                              \
    cin.tie(0);                                                                \
    cout.tie(0)

class DSU {
public:
    vector<int> rank, parent, weight;

    DSU(int n) {
        rank.resize(n, 0);
        parent.resize(n);
        weight.resize(n, -1);

        iota(parent.begin(), parent.end(), 0);
    }

    int find(int x) {
        if (x == parent[x])
            return x;

        return parent[x] = find(parent[x]);
    }

    void unionByRank(int u, int v, int w) {
        int uParent = find(u);
        int vParent = find(v);

        if (uParent == vParent) {
            weight[uParent] &= w;
            return;
        }

        if (rank[uParent] > rank[vParent]) {
            parent[vParent] = uParent;
            weight[uParent] = (weight[uParent] == -1 ? w : weight[uParent] & w & weight[vParent]);
        } else if (rank[uParent] < rank[vParent]) {
            parent[uParent] = vParent;
            weight[vParent] = (weight[vParent] == -1 ? w : weight[vParent] & w & weight[uParent]);
        } else {
            parent[uParent] = vParent;
            rank[vParent]++;
            weight[vParent] = (weight[vParent] == -1 ? w : weight[vParent] & w & weight[uParent]);
        }
    }
};

class Solution {
public:
    vector<int> minimumCost(int n, vector<vector<int>>& edges, vector<vector<int>>& query) {
        INCL();

        DSU dsu(n);

        for (vector<int>& edge : edges) {
            int u = edge[0];
            int v = edge[1];
            int w = edge[2];

            dsu.unionByRank(u, v, w);
        }

        vector<int> result;
        for (vector<int>& que : query) {
            int u = que[0];
            int v = que[1];

            int uParent = dsu.find(u);
            int vParent = dsu.find(v);

            result.push_back(uParent == vParent ? dsu.weight[uParent] : -1);
        }

        return result;
    }
};
```
['Array', 'Bit Manipulation', 'Union Find', 'Graph', 'C++']