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

这篇具有很好参考价值的文章主要介绍了代码随想录| 图论04 查并集 ●查并集理论知识 ●1971.寻找图中是否存在路径 ●684.冗余连接 ●685.冗余连接II。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

#查并集理论知识

 

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

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

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

find的路径压缩:

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

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

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

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

路径压缩长一点写:

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

 路径压缩短一点写:

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

 随想录的查并集模板:

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了

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;
        
    }

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

    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,不能反文章来源地址https://www.toymoban.com/news/detail-601012.html

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 {};
    }

到了这里,关于代码随想录| 图论04 查并集 ●查并集理论知识 ●1971.寻找图中是否存在路径 ●684.冗余连接 ●685.冗余连接II的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 代码随想录图论并查集 第七天 | 685.冗余连接II

    代码随想录图论并查集 第七天 | 685.冗余连接II 一、685.冗余连接II 题目链接:https://leetcode.cn/problems/redundant-connection-ii/ 思路:684.冗余连接中是连通且无环的无向图可直接使用并查集模板,如果想判断集合中是否有环,且那条边构成环,只需要每次加入并查集之前先判断一下是

    2024年02月06日
    浏览(37)
  • 代码随想录图论 第五天| 841.钥匙和房间 463. 岛屿的周长

    代码随想录图论 第五天| 841.钥匙和房间 一、 841.钥匙和房间 题目链接:https://leetcode.cn/problems/keys-and-rooms/ 思路:钥匙就是索引,遍历过就标记,每拿到一个房间的钥匙,直接for循环递归遍历,深度优先直接拿下。 二、463. 岛屿的周长 题目链接:https://leetcode.cn/problems/island-

    2024年02月06日
    浏览(29)
  • 代码随想录图论 第二天 | 695. 岛屿的最大面积 1020. 飞地的数量

    代码随想录图论 第二天 | 695. 岛屿的最大面积 1020. 飞地的数量 一、695. 岛屿的最大面积 题目链接:https://leetcode.cn/problems/max-area-of-island/ 思路:典型的遍历模板题,我采用深度优先,每块岛屿递归遍历的时候计数,递归完比较大小记录最大值。 二、1020. 飞地的数量 题目链接

    2024年02月07日
    浏览(37)
  • 代码随想录Day42-图论:力扣第417m、841m、463e题

    题目链接 代码随想录文章讲解链接 方法一: 用时:1h0m58s 思路 直接找哪些点既可以到达太平洋又可以到达大西洋比较麻烦,换个角度,找到太平洋可以逆流而上到达的点,再找到大西洋可以逆流而上到达的点,两者的交集就是所需要的答案。 用两个二维数组分别记录太平洋

    2024年02月05日
    浏览(44)
  • 代码随想录图论|130. 被围绕的区域 417太平洋大西洋水流问题

    **题目:**给你一个 m x n 的矩阵 board ,由若干字符 ‘X’ 和 ‘O’ ,找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。 题目链接:130. 被围绕的区域 解题思路:在飞地的基础上做改动,使用一个栈存储需要改变的节点 题目 :有一个 m × n 的矩形岛

    2024年02月04日
    浏览(40)
  • 代码随想录Day41-图论:力扣第797m、200m、695m、1020m、130m题

    题目链接 代码随想录文章讲解链接 方法一:DFS 用时:11m43s 思路 时间复杂度: O ( n ⋅ 2 n ) O(n cdot 2^n) O ( n ⋅ 2 n ) ,n是节点个数,最坏情况每个节点都可以去往任意一个在它后面的节点,那么第i个节点去到最后一个节点的路径数就有 2 n − i − 2 2^{n-i-2} 2 n − i − 2 ,就是

    2024年02月06日
    浏览(30)
  • 代码随想录图论 第三天 | 130. 被围绕的区域 417. 太平洋大西洋水流问题

    代码随想录图论 第三天 | 130. 被围绕的区域 417. 太平洋大西洋水流问题 一、130. 被围绕的区域 题目链接:https://leetcode.cn/problems/surrounded-regions/ 思路:题目要求沾边的不动,只改没沾边的,那么可以先dfs遍历4条边,把沾边的O都改成A。然后直接两层for循环遍历整个数组,把O该

    2024年02月07日
    浏览(31)
  • 代码随想录第44天|动态规划:完全背包理论基础 518.零钱兑换II 377. 组合总和 Ⅳ

    代码随想录 (programmercarl.com) 动态规划之完全背包,装满背包有多少种方法?组合与排列有讲究!| LeetCode:518.零钱兑换II_哔哩哔哩_bilibili 完全背包和01背包问题唯一不同的地方就是,每种物品有无限件 。 完全背包中的物品可以添加多次,所以要从小到大遍历: 518. 零钱兑换

    2024年04月25日
    浏览(29)
  • 代码随想录day3|链表理论基础、移除链表元素、设计链表、翻转链表

    1、基本类型:单链表、双链表、循环链表 2、存储方式:和数组不一样,链表是随机存储在内存中,不是连续分配在内存中。 3、链表的定义: 定义了一个数据域,还有一个指针域,并且定义了一个构造函数。 4、链表的操作: 删除节点:  在图中,若需要删除D这个节点,只

    2024年02月05日
    浏览(29)
  • 代码随想录Day3|链表理论基础|203.移除链表元素|707.设计链表|206.反转链表

    虽然以前写过一次链表,但是真的已经忘得一干二净了 链表 :通过 指针 串联在一起的线性结构,每个 节点 都由数据域和指针域组成。 指针域 :存放下一个节点的指针,最后一个节点的指针域指向null,也即空指针 head :链表的入口节点,也即链表的头节点 链表的类型 单

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包