LeetCode 1697. 检查边长度限制的路径是否存在

并查集
将边按照长短进行排序,将小于limit[i] 的边都并入集,这样当查到大于limit[i]的边的时候就可以减少并集的操作。我们也可以对limit进行排序,这样当上一个limit[i]查询完后,集里面就全为小于limit[i + 1] 长度的边,只需要把剩下小于limit[i + 1]边并入集就可以将所有小于limit[i + 1]的边并入集,这个时候再查此时的两个点是否连通(有同一个父节点)

需要对边edgeList和查询queries进行排序,由于最终返回结果按照queries原来顺序进行返回,因此这里使用一个hash映射,映射排序前后的位置。

由于查询表是死的,不会有新的查询加入,因此可以对查询表进行排序,这种方法叫离线查询

class Solution {
public:
    static bool cmp(vector<int>& a, vector<int>& b)
    {
        return a[2] < b[2];
    }
    vector<int> father;
    int find(int u)
    {
        return u == father[u] ? u : father[u] = find(father[u]);
    }
    void merge(int u, int v)
    {
        father[find(v)] = find(u);
    }
    vector<bool> distanceLimitedPathsExist(int n, vector<vector<int>>& edgeList, vector<vector<int>>& queries) {
        father = vector<int>(n);
        for(int i = 0; i < n; i++)
            father[i] = i;
        sort(edgeList.begin(), edgeList.end(), cmp);
        vector<vector<int>> hash = queries;
        for(int i = 0; i < queries.size(); i++)
            hash[i].push_back(i);
        sort(hash.begin(), hash.end(), cmp);    
        vector<bool> res(queries.size(), false);
        int p = 0;
        for(int i = 0; i < hash.size(); i++)
        {
            while(p < edgeList.size() && edgeList[p][2] < hash[i][2])
            {
                merge(edgeList[p][0], edgeList[p][1]);
                p++;
            }
            res[hash[i][3]] = find(hash[i][0]) == find(hash[i][1]);
        }
        return res;
    }
};

你可能感兴趣的:(题,leetcode,算法,数据结构)