并查集-听课笔记

基础:

题目一:

cpp 复制代码
static constexpr  int MAXN = 31;
class Solution {
public:
vector<int> father = vector<int>(MAXN);
int sets;
void build(int m){
    for(int i = 0;i<m;i++){
        father[i] = i;
    }
    sets = m;
}
int find(int i){
    if(i != father[i]) father[i] = find(father[i]);
    return father[i];
}
void combine(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx != fy){
        father[fx] = fy;
        sets--;
    }
}
    int minSwapsCouples(vector<int>& row) {
        int n = row.size();
        build(n/2);
        for(int i = 0;i<n;i+=2){
            combine(row[i]/2,row[i+1]/2);
        }
        return n/2 - sets;
    }
};

题目2:

cpp 复制代码
static constexpr int MAXN = 301;
class Solution {
public:
vector<int> father = vector<int>(MAXN);
int sets;
    void build(int n){
        for(int i = 0;i<n;i++){
            father[i] = i;
        }
        sets = n;
    }
    int find(int i){
        if(i != father[i]) father[i] = find(father[i]);
        return father[i];
    }
    void combine(int x,int y){
        int fx = find(x);
        int fy = find(y);
        if(fx != fy){
            father[fx] = fy;
            sets--;
        }
    }

    int numSimilarGroups(vector<string>& strs) {
        int n = strs.size();
        int m = strs[0].size();
        build(n);
        for(int i = 0;i<n;i++){
            for(int j = i+1;j<n;j++){
                int diff = 0;
                for(int k = 0;k<m && diff<3;k++){
                    if(strs[i][k] != strs[j][k]) diff++;
                }
                if(diff == 0 || diff == 2) combine(i,j);
            }
        }
        return sets;
    }
};

题目3:

cpp 复制代码
class Solution {
public:
static constexpr int MAXN = 100001;
vector<int> father = vector<int>(MAXN);
int cols;
int sets;
int index(int r,int c){
    return r*cols+c;
}
void build(int n,int m,vector<vector<char>>& grid){
    cols = m;
    sets = 0;
    for(int a = 0;a<n;a++){
        for(int b = 0,ind;b<m;b++){
            if(grid[a][b] == '1'){
                ind = index(a,b);
                father[ind] = ind;
                sets++;
            }
        }
    }
}
int find(int i){
    if(i != father[i]) father[i] = find(father[i]);
    return father[i];
}
void combine(int a,int b,int c,int d){
    int fx = find(index(a,b));
    int fy = find(index(c,d));
    if(fx != fy){
        father[fx] = fy;
        sets--;
    }
}
    int numIslands(vector<vector<char>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        build(n,m,grid);
        for(int i = 0;i<n;i++){
            for(int j = 0;j<m;j++){
                if(grid[i][j] == '1'){
                    if(j>0 && grid[i][j-1] == '1') combine(i,j,i,j-1);
                    if(i>0 && grid[i-1][j] == '1') combine(i,j,i-1,j);
                }
            }
        }
        return sets;
    }
};

题目4:

cpp 复制代码
#define MAXN 1001
#define MAXNCOORD 10001
int father[MAXN];
int sets;
void build(int n){
    for(int i = 0;i<n;i++){
        father[i] = i;
    }
    sets = n;
}
int find(int i){
    if(i != father[i]){
        father[i] = find(father[i]);
    }
    return father[i];
}
void combine(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx != fy){
        father[fx] = fy;
        sets--;
    }
}
int removeStones(int** stones, int stonesSize, int* stonesColSize) {
    int n = stonesSize;
    build(n);
    int rowFirst[MAXNCOORD];
    int colFirst[MAXNCOORD];
    memset(rowFirst,-1,sizeof(rowFirst));
    memset(colFirst,-1,sizeof(colFirst));
    for(int i = 0;i<n;i++){
        int row = stones[i][0];
        int col = stones[i][1];
        if(rowFirst[row] == -1){
            rowFirst[row] = i;
        }else{
            combine(rowFirst[row],i);
        }
        if(colFirst[col] == -1){
            colFirst[col] = i;
        }else{
            combine(colFirst[col],i);
        }
    }
    return n-sets;
}

题目5:

cpp 复制代码
class Solution {
public:
static constexpr int MAXN = 100001;
vector<int> father = vector<int>(MAXN);
vector<bool> secret = vector<bool>(MAXN);
void build(int n,int firstPerson){
    for(int i = 0;i<n;i++){
        father[i] = i;
        secret[i] = false;
    }
    father[firstPerson] = 0;
    secret[0] = true;
}
int find(int i){
    if(i != father[i]) father[i] = find(father[i]);
    return father[i];
}
void combine(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx != fy){
        father[fx] = fy;
        secret[fy] = secret[fy] || secret[fx];
    }
}

    vector<int> findAllPeople(int n, vector<vector<int>>& meetings, int firstPerson) {
        build(n,firstPerson);
        sort(meetings.begin(),meetings.end(),[](const vector<int>& a,const vector<int>& b){
            return a[2]<b[2];
        });
        int m = meetings.size();
        for(int l = 0,r;l<m;){
            r = l;
            while(r+1<m && meetings[l][2] == meetings[r+1][2]){
                r++;
            }
            for(int i = l;i<=r;i++){
                combine(meetings[i][0],meetings[i][1]);
            }
            for(int i = l,a,b;i<=r;i++){
                a = meetings[i][0];
                b = meetings[i][1];
                if(!secret[find(a)]){
                    father[a] = a;
                }
                if(!secret[find(b)]){
                    father[b] = b;
                }
            }
            l = r+1;
        }
        vector<int> ans;
        for(int i = 0;i<n;i++){
            if(secret[find(i)]) ans.push_back(i);
        }
        return ans;
    }
};

题目6:

cpp 复制代码
static constexpr int MAXN = 300001;
class Solution {
public:
vector<int> father = vector<int>(MAXN);
vector<int> maxcnt = vector<int>(MAXN);
void build(int n){
    for(int i = 0;i<n;i++){
        father[i] = i;
        maxcnt[i] = 1;
    }
}
int find(int i){
    if(i != father[i]) father[i] = find(father[i]);
    return father[i];
}
int combine(int x,int y,vector<int>& vals){
    int fx = find(x);
    int fy = find(y);
    int path = 0;
    if(vals[fx]>vals[fy]){
        father[fy] = fx;
    }else if(vals[fx]<vals[fy]){
        father[fx] = fy;
    }else{
        path = maxcnt[fx] * maxcnt[fy];
        father[fy] = fx;
        maxcnt[fx] += maxcnt[fy];
    }
    return path;
}
    int numberOfGoodPaths(vector<int>& vals, vector<vector<int>>& edges) {
        int n = vals.size();
        build(n);
        sort(edges.begin(),edges.end(),[&vals](const vector<int>& a,const vector<int>& b){
            return max(vals[a[0]],vals[a[1]]) < max(vals[b[0]],vals[b[1]]);
        });
        int ans = n;
        for(auto & edge : edges){
            ans += combine(edge[0],edge[1],vals);
        }
        return ans;
    }
};

题目7:

cpp 复制代码
static constexpr int MAXN = 301;

class Solution {
public:
    vector<bool> virus = vector<bool>(MAXN);
    vector<int> infect = vector<int>(MAXN);
    vector<int> father = vector<int>(MAXN);
    vector<int> size = vector<int>(MAXN);
    vector<int> cnts = vector<int>(MAXN);

    void build(int n, vector<int>& initial) {
        for (int i = 0; i < n; i++) {
            virus[i] = false;
            cnts[i] = 0;
            infect[i] = -1;       
            father[i] = i;       
            size[i] = 1;
        }
        for (int i : initial) {
            virus[i] = true;
        }
    }

    int find(int i) {
        if (i != father[i]) father[i] = find(father[i]);
        return father[i];
    }

    void combine(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if (fx != fy) {
            father[fx] = fy;
            size[fy] += size[fx];
        }
    }

    int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
        int n = graph.size();
        build(n, initial);
        
        // 1. 合并所有未被感染的节点
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (graph[i][j] == 1 && !virus[i] && !virus[j]) {
                    combine(i, j);
                }
            }
        }

        // 2. 标记每个连通块被哪些感染源连接
        for (int sick : initial) {
            for (int neighbor = 0; neighbor < n; neighbor++) {
                if (sick != neighbor && !virus[neighbor] && graph[sick][neighbor] == 1) {
                    int fn = find(neighbor);
                    if (infect[fn] == -1) {
                        infect[fn] = sick;
                    } else if (infect[fn] != -2 && infect[fn] != sick) {
                        infect[fn] = -2;
                    }
                }
            }
        }

        // 3. 统计每个感染源能"拯救"的节点数
        for (int i = 0; i < n; i++) {
            if (i == find(i) && infect[i] >= 0) {
                cnts[infect[i]] += size[i]; // 修复3:下标改为 infect[i]
            }
        }

        // 4. 排序并找到最优解
        sort(initial.begin(), initial.end());
        int ans = initial[0];
        int max_cnt = cnts[ans];
        for (int i : initial) {
            if (cnts[i] > max_cnt) {
                ans = i;
                max_cnt = cnts[i];
            }
        }
        return ans;
    }
};

以上题目和解答来自B站左神(左程云)

相关推荐
码流子4 小时前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
彧azz4 小时前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
another heaven5 小时前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark5 小时前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218615 小时前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法
陈卫军老师5 小时前
陈卫军:把口味写在一张纸上,店才稳得住
经验分享·笔记·流量运营
`流年づ6 小时前
人工智能学习笔记 - 补充
人工智能·笔记·深度学习·学习
mikuyyds6 小时前
geo-toolbox 水文插件算法解析:从 Muskingum 到 Muskingum-Cunge
算法·rust·gis
Omics Pro6 小时前
斯坦福Nature+Science|广义虚拟细胞基础大模型
数据库·人工智能·算法·机器学习·自然语言处理