051.并查集

模板0

class UF{
    private:
    vector<int>fa;
    public:
    UF(int n):fa(n){
        for(int i=0;i<n;++i){
            fa[i]=i;
        }
    }
    int find(int x){
        if(x!=fa[x]){
            fa[x]=find(fa[x]);
        }
        return fa[x];
    }
    bool check(int a,int b){
        return find(a)==find(b);
    }
    int merge(int a,int b){
        int A=find(a);
        int B=find(b);
        if(A==B)return 0;//已连通返回0
        fa[A]=B;
        return 1;//连通成功返回1
    }
};

模板1

class UF{
    private:
    int cnt;//连通分量数量
    vector<int>fa;
    public:
    UF(int n):cnt(n),fa(n){
        for(int i=0;i<n;++i){
            fa[i]=i;
        }
    }
    int find(int x){
        if(x!=fa[x]){
            fa[x]=find(fa[x]);
        }
        return fa[x];
    }
    bool check(int a,int b){
        return find(a)==find(b);
    }
    int merge(int a,int b){
        int A=find(a);
        int B=find(b);
        if(A==B)return 0;//已连通返回0
        fa[A]=B;
        cnt--;
        return 1;//连通成功返回1
    }
    int count(){
        return cnt;
    }
};

模板2 小挂大

class UF{
    private:
    int cnt;
    vector<int>siz;
    vector<int>fa;
    public:
    UF(int n):cnt(n),fa(n),siz(n){
        for(int i=0;i<n;++i){
            fa[i]=i;
            siz[i]=1;
        }
    }
    int find(int x){
        if(x!=fa[x]){
            fa[x]=find(fa[x]);
        }
        return fa[x];
    }
    bool check(int a,int b){
        return find(a)==find(b);
    }
    int merge(int a,int b){
        int A=find(a);
        int B=find(b);
        if(A==B)return 0;
        if(siz[A]>siz[B]){
            fa[B]=A;
            siz[A]+=siz[B];
        }
        else{
            fa[A]=B;
            siz[B]+=siz[A];
        }
        cnt--;
        return 1;
    }
    int count(){
        return cnt;
    }
};

静态

const int N=1e5+5;

int fa[N];
int siz[N];
int cnt;

void built(int n){
    cnt=n;
    for(int i=0;i<n;++i){
        fa[i]=i;
        siz[i]=1;
    }
}
int find(int x){
    if(fa[x]!=x){
        fa[x]=find(fa[x]);
    }
    return fa[x];
}
bool check(int a,int b){
    return find(a)==find(b);
}
int merge(int a,int b){
    int A=find(a);
    int B=find(b);
    if(A==B)return 0;
    if(siz[A]>siz[B]){
        fa[B]=A;
        siz[A]+=siz[B];
    }
    else{
        fa[A]=B;
        siz[B]+=siz[A];
    }
    cnt--;
    return 1;
}

习题

差分约束

leetcode 990

class Solution {
    vector<int>fa;
void built(int n){
    fa.resize(n);
    for(int i=0;i<n;++i){
        fa[i]=i;
    }
}
int find(int x){
    if(fa[x]!=x){
        fa[x]=find(fa[x]);
    }
    return fa[x];
}
bool check(int a,int b){
    return find(a)==find(b);
}
void merge(int a,int b){
    int A=find(a);
    int B=find(b);
    fa[A]=B;
}
public:
    bool equationsPossible(vector<string>& equations) {
        built(26);
        for(auto x:equations){
            if(x[1]=='='){
                merge(x[0]-'a',x[3]-'a');
            }
        }
        for(auto x:equations){
            if(x[1]=='!'){
                if(check(x[0]-'a',x[3]-'a')){
                    return 0;
                }
            }
        }
        return 1;
    }
};

情侣牵手

leetcode 765

class Solution {
    class UF{
        vector<int>fa;
        int find(int x){
            if(x!=fa[x]){
                fa[x]=find(fa[x]);
            }
            return fa[x];
        }
        public:
        UF(int n):fa(n){
            for(int i=0;i<n;++i)fa[i]=i;
        }
        void merge(int a,int b){
            fa[find(a)]=find(b);
        }
        bool check(int a,int b){
            return find(a)==find(b);
        }
    };
public:
    int minSwapsCouples(vector<int>& row) {
        int n=row.size();
        int cnt=n/2;
        UF st(cnt);
        for(int i=0;i+1<n;i+=2){
            int a=row[i]>>1;
            int b=row[i+1]>>1;
            if(!st.check(a,b)){
                st.merge(a,b);
                cnt--;
            }
        }
        return n/2-cnt;
    }
};

相似字符串

leetcode 839

class Solution {
    class UF{
        vector<int>fa;
        int find(int x){
            if(x!=fa[x]){
                fa[x]=find(fa[x]);
            }
            return fa[x];
        }
        public:
        UF(int n):fa(n){
            for(int i=0;i<n;++i)fa[i]=i;
        }
        void merge(int a,int b){
            fa[find(a)]=find(b);
        }
        bool check(int a,int b){
            return find(a)==find(b);
        }
    };
public:
    int numSimilarGroups(vector<string>& strs) {
        int n=strs.size();
        int m=strs[0].size();
        int cnt=n;
        UF st(n);
        for(int i=0;i+1<n;++i){
            for(int j=i+1;j<n;++j){
                if(!st.check(i,j)){
                    int diff=0;
                    for(int k=0;k<m;++k){
                        if(strs[i][k]!=strs[j][k]){
                            diff++;
                        }
                    }
                    if(diff==0||diff==2){
                        st.merge(i,j);
                        cnt--;
                    }
                }
            }
        }
        return cnt;
    }
};

移除石头

leetcode 947

class Solution {
     class UF{
        vector<int>fa;
        int find(int x){
            if(x!=fa[x]){
                fa[x]=find(fa[x]);
            }
            return fa[x];
        }
        public:
        UF(int n):fa(n){
            for(int i=0;i<n;++i)fa[i]=i;
        }
        int merge(int a,int b){
            if(check(a,b))return 0;
            fa[find(a)]=find(b);
            return 1;
        }
        bool check(int a,int b){
            return find(a)==find(b);
        }
    };
public:
    int removeStones(vector<vector<int>>& stones) {
        int n=stones.size();
        UF st(n);
        int cnt=0;
        unordered_map<int,int>row;
        unordered_map<int,int>col;
        for(int i=0;i<n;++i){
            int x=stones[i][0];
            int y=stones[i][1];
            if(row.count(x)==0){
                row[x]=i;
            }
            else cnt+=st.merge(row[x],i);
            if(col.count(y)==0){
                col[y]=i;
            }
            else cnt+=st.merge(col[y],i);
        }
        return  cnt;
    }
};

知道秘密的专家

leetcode 2092

class Solution {
    vector<int>fa;
    vector<int>vis;
    int find(int x){
        if(x!=fa[x]){
            fa[x]=find(fa[x]);
        }
        return fa[x];
    }
    void merge(int a,int b){
        int A=find(a);
        int B=find(b);
        fa[A]=B;
        if(vis[A]||vis[B]){
            vis[A]=vis[B]=1;
        }
    }
public:
    vector<int> findAllPeople(int n, vector<vector<int>>& met, int fir) {
        sort(met.begin(),met.end(),[&](auto &a,auto &b){return a[2]<b[2];});
        fa.resize(n);
        vis.resize(n);
        for(int i=0;i<n;++i){
            fa[i]=i;
            vis[i]=0;
        }
        vis[0]=vis[fir]=1;
        fa[fir]=0;
        int m=met.size();
        for(int l=0;l<m;){
            int r=l;
            while(r+1<m&&met[l][2]==met[r+1][2])r++;
            for(int i=l;i<=r;++i){
                int x=met[i][0];
                int y=met[i][1];
                merge(x,y);
            }
            for(int i=l;i<=r;++i){
                int x=met[i][0];
                int y=met[i][1];
                if(vis[find(x)]==0){
                    fa[x]=x;
                }
                if(vis[find(y)]==0){
                    fa[y]=y;
                }
            }
            l=r+1;
        }
        vector<int>ans;
        for(int i=0;i<n;++i){
            if(vis[find(i)])ans.push_back(i);
        }
        return ans;
    }
};

好路径数目

leetcode 2421

class Solution {
    vector<int>fa;
    vector<int>cnt;
    void built(int n){
        fa.resize(n);
        cnt.resize(n);
        for(int i=0;i<n;++i){
            cnt[i]=1;
            fa[i]=i;
        }
    }
    int find(int x){
        if(fa[x]!=x){
            fa[x]=find(fa[x]);
        }
        return fa[x];
    }
    int merge(int a,int b,vector<int>&v){
        int A=find(a);
        int B=find(b);
        int path=0;
        if(v[A]>v[B]){
            fa[B]=A;
        }
        else if(v[A]<v[B]){
            fa[A]=B;
        }
        else{
            path=cnt[A]*cnt[B];
            fa[A]=B;
            cnt[B]+=cnt[A];
        }
        return path;
    }
public:
    int numberOfGoodPaths(vector<int>& v, vector<vector<int>>& e) {
        int n=v.size();
        built(n);
        sort(e.begin(),e.end(),[&](auto &a,auto &b){
            return max(v[a[0]],v[a[1]])<max(v[b[0]],v[b[1]]);
        });
        long ans=n;
        for(auto x:e){
            ans+=merge(x[0],x[1],v);
        }
        return ans;
    }
};

病毒转播

leetcode 928

class Solution {
    vector<int>fa;
    vector<int>siz;
    vector<bool>isinit;
    vector<int>init;
    vector<int>cnt;
    void built(int n){
        fa.resize(n);
        siz.resize(n);
        isinit.resize(n);
        init.resize(n);
        cnt.resize(n);
        for(int i=0;i<n;++i){
            cnt[i]=0;
            fa[i]=i;
            siz[i]=1;
            isinit[i]=0;
            init[i]=-1;
        }
    }
    int find(int x){
        if(x!=fa[x]){
            fa[x]=find(fa[x]);
        }
        return fa[x];
    }
    void merge(int a,int b){
        int A=find(a);
        int B=find(b);
        if(A==B)return;
        fa[A]=B;
        siz[B]+=siz[A];
    }
public:
    int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
        int n=graph.size();
        built(n);
        for(int x:initial){
            isinit[x]=1;
        }
        for(int i=0;i+1<n;++i){
            for(int j=i+1;j<n;++j){
                if(!isinit[i]&&!isinit[j]&&graph[i][j]==1){
                    merge(i,j);
                }
            }
        }
        for(int x:initial){
            for(int i=0;i<n;++i){
                if(graph[x][i]&&!isinit[i]){
                    int f=find(i);
                    if(init[f]==-1){
                        init[f]=x;
                    }
                    else{
                        if(init[f]!=x)init[f]=-2;
                    }
                }
            }
        }
        for(int i=0;i<n;++i){
            if(find(i)==i&&init[i]!=-1&&init[i]!=-2){
                cnt[init[i]]+=siz[i];
            }
        }
        int ans=initial[0];
        for(int x:initial){
            if(cnt[x]>cnt[ans]){
                ans=x;
            }
            if(cnt[x]==cnt[ans]){
                ans=min(ans,x);
            }
        }
        return ans;
    }
};

限制边长的路径

leetcode 1697

class Solution {
    vector<int>fa;
    void built(int n){
        fa.resize(n);
        for(int i=0;i<n;++i){
            fa[i]=i;
        }
    }
    int find(int x){
        if(x!=fa[x]){
            fa[x]=find(fa[x]);
        }
        return fa[x];
    }
    bool check(int a,int b){
        return find(a)==find(b);
    }
    bool merge(int a,int b){
        int A=find(a);
        int B=find(b);
        if(A==B)return 0;
        fa[A]=B;
        return 1;
    }
public:
    vector<bool> distanceLimitedPathsExist(int n, vector<vector<int>>& e, vector<vector<int>>& Q) {
        built(n);
        int m=e.size();
        int q=Q.size();
        for(int i=0;i<q;++i){
            Q[i].push_back(i);
        }
        sort(Q.begin(),Q.end(),[&](auto a,auto b){return a[2]<b[2];});
        sort(e.begin(),e.end(),[&](auto a,auto b){return a[2]<b[2];});
        int i=0;
        vector<bool>ans(q);
        for(auto x:Q){
            int id=x[3];
            int u=x[0],v=x[1],k=x[2];
            while(i<m&&e[i][2]<k){
                merge(e[i][0],e[i][1]);
                ++i;
            }
            ans[id]=(check(u,v));
        }
        return ans;
    }
};
posted @ 2026-01-19 00:10  射杀百头  阅读(2)  评论(0)    收藏  举报