并查集-听课笔记

基础:

题目一:

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站左神(左程云)

相关推荐
hetao173383717 分钟前
2026-11-02 hetao1733837 的刷题记录
c++·算法
Geektec20 分钟前
IMU 选型完全指南:从硬件参数到算法融合的系统工程视角
算法·imu·陀螺仪·加速度计·元器件选型
CQU_JIAKE24 分钟前
11.2【A】
算法
Godspeed Zhao1 小时前
从零开始学AI21——决策树
算法·决策树·机器学习
开开心心就好1 小时前
网页图片批量下载工具,输入链接就保存
服务器·算法·leetcode·支持向量机·pdf·ocr·1024程序员节
无心水1 小时前
20、大数据架构设计理论与实践 核心考点与学习笔记
大数据·笔记·学习·架构师·系统架构设计师·软考系统架构设计师·架构设计师
snysy2 小时前
WordPress伪静态404故障排查笔记
android·笔记·wordpress
Z21-X2 小时前
云原生运维实战笔记:华为云计算与网络类服务全景解析
运维·笔记·学习·云原生·华为云
半壶清水2 小时前
[软考网规考点笔记]-局域网之冗余网关技术
网络·笔记·智能路由器
LK_072 小时前
【Agent】工具调用的安全边界:从模型输出到程序执行
人工智能·笔记·python·agent