b_lc_带阈值的图连通性(反向思维+并查集)

x 和 y 的两座城市直接连通的前提是: x 和 y 的公因数中,至少有一个 严格大于 某个阈值 threshold;
给你两个整数 n 和 threshold ,以及一个待查询数组,请你判断每个查询 queries[i] = [ai, bi] 指向的城市 ai 和 bi 是否连通
1<n<1e4

思路
正向枚举所有点然后检查是否连通会超时,更优雅的做法是先预处理每个点 i (i∈[thre,n]) 的所有因数到一个连通块中;
这样做,查询的时候就可以用 logn 时间找到两城市是否连通(因为两个点有>threshold的公因数他们必定在一个连通块中)

const int N=1e4+5;
class Solution {
public:
    int fa[N];
    int find(int u) {return fa[u]==u ? u : fa[u]=find(fa[u]);}
    void merge(int u, int v) {
        fa[find(u)]=fa[find(v)];
    }
    vector<bool> areConnected(int n, int thre, vector<vector<int>>& qs) {
        int m=qs.size();
        vector<bool> ans(m);
        for (int i=1; i<=n; i++) fa[i]=i;
        
        for (int i=thre; i<=n; i++)
        for (int j=1; j<=i/j; j++) if (i%j==0) {
            if (j>thre) merge(i,j);
            if (i/j>thre) merge(i,i/j); //j是i的因子,i/j也是啊
        }
        for (int i=0; i<m; i++) if (find(qs[i][0])==find(qs[i][1]))
            ans[i]=true;
       return ans; 
    }
};
posted @ 2020-10-18 20:10  童年の波鞋  阅读(126)  评论(0编辑  收藏  举报