代码随想录| 图论04 查并集 ●查并集理论知识 ●1971.寻找图中是否存在路径 ●684.冗余连接 ●685.冗余连接II

#查并集理论知识

并查集用处:解决连通性问题

  • 将两个元素添加到一个集合中。
  • 判断两个元素在不在同一个集合

思路:将三个元素A,B,C (分别是数字)放在同一个集合,其实就是将三个元素连通在一起,如何连通:只需要用一个一维数组来表示,即:father[A] = B,father[B] = C 这样就表述 A 与 B 与 C连通了(有向连通图)。如果几个元素的根是同一个,代表在同一集合。

find的路径压缩:

就需要 路径压缩,将非根节点的所有节点直接指向根节点

路径压缩长一点写:

cpp 复制代码
int find(int u) {
    if (u == father[u]) return u;
    else return father[u] = find(father[u]); // 路径压缩
}

路径压缩短一点写:

cpp 复制代码
int find(int u) {
    return u == father[u] ? u : father[u] = find(father[u]);
}

随想录的查并集模板:

cpp 复制代码
int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好
vector<int> father = vector<int> (n, 0); // C++里的一种数组结构

// 并查集初始化
void init() {
    for (int i = 0; i < n; ++i) {
        father[i] = i;
    }
}
// 并查集里寻根的过程
int find(int u) {
    return u == father[u] ? u : father[u] = find(father[u]); // 路径压缩
}

// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}

// 将v->u 这条边加入并查集
void join(int u, int v) {
    u = find(u); // 寻找u的根
    v = find(v); // 寻找v的根
    if (u == v) return ; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
    father[v] = u;
}

# 1971.寻找图中是否存在路径 并查集基础题目

我用dfs做的,自己处理edge信息,梦回3343 3391了

cpp 复制代码
void dfs(int start, int dest, vector<vector<int>>& edges, vector<vector<int>> &path, vector<bool> &v,bool &flag){
        if(start==dest){
            flag=true;
            return;
        }
        v[start]=true;
        for(int i=0;i<path[start].size();i++){
            if(!v[path[start][i]]) dfs(path[start][i], dest,edges,path,v,flag);
        }
    }


    bool validPath(int n, vector<vector<int>>& edges, int source, int dest) {
        vector<vector<int>> path(n);
        vector<bool> v(n,false);
        bool flag=false;

        for(int i=0;i<edges.size();i++){
            //edges[i] = [ui, vi]   edges[i][0] edges[i][1]
            path[edges[i][0]].push_back(edges[i][1]);
            path[edges[i][1]].push_back(edges[i][0]);
        }

        dfs(source,dest,edges,path,v,flag);
        return flag;
        
    }

查并集做法:(要把模板学会记住)自己写的:

cpp 复制代码
    int n=200001;
    vector<int> father=vector<int> (n,0);

    void init(){
        for(int u=0;u<n;u++) father[u]=u;
    }

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

    bool isSame(int u, int v){
        u=find(u);
        v=find(v);
        return u==v;
    }

    void join(int u, int v){
        u=find(u);
        v=find(v);
        if(u!=v) father[u]=v;
    }

    bool validPath(int n, vector<vector<int>>& edges, int source, int dest) {
  
        init();
        for(int i=0;i<edges.size();i++){
            join(edges[i][0],edges[i][1]);
        }
        return isSame(source,dest);
    }

记住,所有函数最外面这么写会错:

int n=200001;

vector<int> father(n,0);

但是vector<int> father = vector<int>(n,0); 这样写就可以(我不知道为什么

因为:在C++中,同一个编译单元(通常就是一个源文件)内的全局变量的初始化顺序是不确定的。编译器可能以任何顺序初始化它们,这个顺序通常取决于编译器的实现,是不可预测的。


#684.冗余连接

我没想到思路

判断成环:已经有同样的根,但是又来一个edge连接两者。

join易错点:最后一步 father[u]=v, father[v]=u 都可以,但是被赋值的一定要是father,不能反

cpp 复制代码
int n=1001;
    vector<int> father=vector<int>(n,0);

    void init(){
        for(int u=0;u<n;u++) father[u]=u;
    }

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

    void join(int u, int v){
        u=find(u);
        v=find(v);
        
        if(u!=v) father[v]=u;
    }

    bool isSame(int u, int v){
        u=find(u);
        v=find(v);
        return u==v;
    }

    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        init();
        for(int i=0;i<edges.size();i++){
            if(isSame(edges[i][0],edges[i][1])) return edges[i];
            join(edges[i][0],edges[i][1]);
             
        }
        return {};
    }
相关推荐
pianmian13 分钟前
python数据结构基础(7)
数据结构·算法
闲晨5 分钟前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
UestcXiye1 小时前
《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
c++·计算机网络·ip·tcp
好奇龙猫2 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
霁月风3 小时前
设计模式——适配器模式
c++·适配器模式
sp_fyf_20243 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
香菜大丸3 小时前
链表的归并排序
数据结构·算法·链表
jrrz08283 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time3 小时前
golang学习2
算法
咖啡里的茶i3 小时前
Vehicle友元Date多态Sedan和Truck
c++