1697. 檢查邊長度限制的路徑是否存在

困難 並查集

思路

與其每次查詢都跑一遍 bfs/dfs,不如將查詢的順序調動。
對查詢跟邊排序,排序時依據distlimit
此時每次查詢的限制條件,只會越來越放寬,
這樣對於後面的查詢來說,此時要處理limit為 10 的查詢時,先將所有長度 < 10 的邊都合併,
然後直接查詢兩點是否連通就好,使用並查集來合併節點。

程式碼

並查集

class Solution {
private:
    static const int MX = 1e5+1;
    int parent[MX];
    void build(int n) {
        iota(parent, parent + n, 0);
    }
    int find(int x) {
        if(x != parent[x]) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }
    bool isSameSet(int x, int y) {
        return find(x) == find(y);
    }
    void unite(int x, int y) {
        parent[find(x)] = parent[find(y)];
    }
public:
    vector<bool> distanceLimitedPathsExist(int n, vector<vector<int>>& edgeList, vector<vector<int>>& queries) {
        build(n);
        for(int i = 0; i < queries.size(); i++) {
            queries[i].push_back(i); // 後面排序會打亂順序,事先加入下標,以供填入答案
        }
        sort(queries.begin(), queries.end(), [&](vector<int>& a, vector<int>& b) {
            return a[2] < b[2];
        });
        sort(edgeList.begin(), edgeList.end(), [&](vector<int>& a, vector<int>& b) {
            return a[2] < b[2];
        });
        vector<bool> res(queries.size());
        int m = edgeList.size();
        int i = 0;
        for(auto& vec : queries) {
            int p = vec[0], q = vec[1], limit = vec[2];
            while(i < m && edgeList[i][2] < limit) {
                unite(edgeList[i][0], edgeList[i][1]);
                i++;
            }
            if(isSameSet(p, q)) res[vec[3]] = true;
            else res[vec[3]] = false;
        }
        return res;      
    }
};

複雜度分析

  • 時間複雜度:O(ElogE+QlogQ+Qα(n))O(E\log{E}+Q\log{Q}+Q\alpha(n))EE 是邊的個數,QQ 是查詢次數
  • 空間複雜度:O(N+Q)O(N+Q)

顯示設定

背景線條
顯示背景網格線條
懸停發光
滑鼠懸停時顯示霓虹效果
聚光燈
跟隨滑鼠的聚光燈效果
背景透明度
開啟透明玻璃效果
主題顏色
自訂主要顏色