并查集-听课笔记

基础:

题目一:

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

相关推荐
Gigavision12 分钟前
CAS(ME)²数据集 感知图卷积网络算法 CAS(ME)²数据集下载
网络·算法
志尊宝20 分钟前
Vue3 零基础每日笔记(080):Vue3 + ECharts 数据可视化——封装可复用图表组件
前端·javascript·vue.js·笔记·信息可视化·echarts
杜 硕31 分钟前
快速排序02
算法·排序算法
沪上企服通32 分钟前
从票据采集到凭证生成:代账 pipeline 的 OCR、查重与规则引擎设计笔记
笔记·ocr
careathers38 分钟前
【数据结构】二叉树拓展
数据结构·算法
java_nnnn1 小时前
LeetCode刷题滑动窗口(长度最小的子数组)
算法·leetcode·职场和发展
@atweiwei1 小时前
训练 AI 大模型系列之 LoRA:不动模型本体,靠一条低秩旁路改专长(附完整手算算例)
人工智能·算法·ai·语言模型·rag
yi0111 小时前
DAY27: LeetCode 110. 平衡二叉树 | 在递归中判断是否平衡
人工智能·笔记·python·算法·leetcode·二叉树·递归
9624561 小时前
餐饮 SaaS 优惠券系统架构演进(七)营销定价引擎设计:活动、会员价、优惠券、买赠如何在同一 PriceQuote 中可解释地组合
java·运维·算法
ab1237681 小时前
MQTT笔记
java·笔记·mqtt·学习