2022-12-14 LeetcCode 1697.检查边长度限制的路径是否存在【并查集+离线思想】

传送门: 1697. 检查边长度限制的路径是否存在

题目:

给你一个 n 个点组成的无向图边集 edgeList ,其中 edgeList[i] = [ui, vi, disi] 表示点 ui 和点 vi 之间有一条长度为 disi 的边。请注意,两个点之间可能有 超过一条边 。

给你一个查询数组queries ,其中 queries[j] = [pj, qj, limitj] ,你的任务是对于每个查询 queries[j] ,判断是否存在从 pj 到 qj 的路径,且这条路径上的每一条边都 严格小于 limitj 。

请你返回一个 布尔数组 answer ,其中 answer.length == queries.length ,当 queries[j] 的查询结果为 true 时, answer 第 j 个值为 true ,否则为 false 。

数据范围:

  • 2 < = n < = 1 0 5 2 <= n <= 10^5 2<=n<=105
  • 1 < = e d g e L i s t . l e n g t h , q u e r i e s . l e n g t h < = 1 0 5 1 <= edgeList.length, queries.length <= 10^5 1<=edgeList.length,queries.length<=105
  • e d g e L i s t [ i ] . l e n g t h = = 3 edgeList[i].length == 3 edgeList[i].length==3
  • q u e r i e s [ j ] . l e n g t h = = 3 queries[j].length == 3 queries[j].length==3
  • 0 < = u i , v i , p j , q j < = n − 1 0 <= u_i, v_i, p_j, q_j <= n - 1 0<=ui,vi,pj,qj<=n1
  • u i ! = v i u_i != v_i ui!=vi
  • p j ! = q j p_j != q_j pj!=qj
  • 1 < = d i s i , l i m i t j < = 1 0 9 1 <= dis_i, limit_j <= 10^9 1<=disi,limitj<=109
  • 两个点之间可能有 多条 边。

解题思路:

考虑 离线思想 ,先将边按 边权 从小到大排序,然后将 q u e r i e s queries queries 中的 l i m i t limit limit 从小到大排序。然后考虑对于当前的查询,将小于 当前 l i m i t limit limit 的边挑出来,用并查集去判断点是否联通,就可以判断是否满足要求。

这种思想值得我学习。

AC代码:

class Solution {
public:

    const static int MAXN = 1e5 + 10;

    vector<bool>res;
    int p[MAXN];

    static int cmp(const vector<int>&a, const vector<int>&b){
        return a[2] < b[2];
    }

    int Fa(int x){
        return x == p[x] ? x : p[x] = Fa(p[x]);
    }

    void merge(int u,int v){
        int fu = Fa(u),fv = Fa(v);
        if(fu != fv){
            p[fu] = fv;
        }
    }

    vector<bool> distanceLimitedPathsExist(int n, vector<vector<int>>& edgeList, vector<vector<int>>& queries) {
        int m = edgeList.size(),queriesLen = queries.size();

        for(int i = 0;i < n;i ++){
            p[i] = i;
        }
        for(int i = 0;i < queriesLen;i ++){
            res.push_back(false);
            queries[i].push_back(i);
        }

        sort(edgeList.begin(),edgeList.end(),cmp);
        sort(queries.begin(),queries.end(),cmp);

        int now = 0;

        for(int i = 0;i < queriesLen;i ++){
            int limit = queries[i][2];
            while(now < m && edgeList[now][2] < limit){
                int u = edgeList[now][0],v = edgeList[now][1];
                merge(u,v);
                now ++;
            }
            int u = queries[i][0],v = queries[i][1];
            if(Fa(u) == Fa(v)){
                res[queries[i][3]] = true;
            }
        }

        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值