当前位置: 首页 > article >正文

代码随想录算法训练营day55:图论05:并查集

并查集理论基础

应用场景:

并查集常用来解决连通性问题。

大白话就是当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。

功能:

  1. 初始化
  2. 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个
  3. 将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上
  4. 判断两个节点是否在同一个集合,函数:isSame(int u, int v),就是判断两个节点是不是同一个根节点

实现的数据结构:

只需要用一个一维数组来表示,即:father[A] = B,father[B] = C 这样就表述 A 与 B 与 C连通了(有向连通图)。相当于记录根结点!

经过路径压缩,直接指向最初的根结点

代码:

初始化:需要让每个节点都指向自己

// 并查集初始化
void init() {
    for (int i = 0; i < n; ++i) {
        father[i] = i;
    }
}

查找根

可进行路径压缩优化

// 并查集里寻根的过程
int find(int u) {
    if (u == father[u]) return u; // 如果根就是自己,直接返回
    else return find(father[u]); // 如果根不是自己,就根据数组下标一层一层向下找
}

判断两个元素是否在同一个集合里

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

**路径压缩:一旦应用find,直接把孩子连在根结点上

// 并查集里寻根的过程
int find(int u) {
    if (u == father[u]) return u;
    else return father[u] = find(father[u]); // 路径压缩
}

 进一步优化:合树的时候,矮树并入高树

用路径压缩记录rank就不准了!所以不用

void join(int u, int v) {
    u = find(u); // 寻找u的根
    v = find(v); // 寻找v的根

    if (rank[u] <= rank[v]) father[u] = v; // rank小的树合入到rank大的树
    else father[v] = u;

    if (rank[u] == rank[v] && u != v) rank[v]++; // 如果两棵树高度相同,则v的高度+1,因为上面 if (rank[u] <= rank[v]) father[u] = v; 注意是 <=
}

107. 寻找存在的路径

卡码网题目链接(ACM模式)(opens new window)

题目描述

给定一个包含 n 个节点的无向图中,节点编号从 1 到 n (含 1 和 n )。

你的任务是判断是否有一条从节点 source 出发到节点 destination 的路径存在。

输入描述

第一行包含两个正整数 N 和 M,N 代表节点的个数,M 代表边的个数。

后续 M 行,每行两个正整数 s 和 t,代表从节点 s 与节点 t 之间有一条边。

最后一行包含两个正整数,代表起始节点 source 和目标节点 destination。

输出描述

输出一个整数,代表是否存在从节点 source 到节点 destination 的路径。如果存在,输出 1;否则,输出 0。

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h>
#include <string.h>
#include <math.h>


int find(int *father,int q){
    if(q==father[q]) return q;//自己 和 根结点相同——自己就是根结点,直接return自己
    else {
        father[q]=find(father,father[q]);//不相同,则查找自己的上一层结点,一直到q==father【q】的情况才返回
        return father[q];
    }
}

void join(int x,int y,int* father){
    int hx=find(father,x);
    int hy=find(father,y);
    if(hx==hy) return;
    father[hx]=hy;
}

bool issame(int x,int y,int*father){
    int hx=find(father,x);
    int hy=find(father,y);
    if(hx==hy) return true;
    else return false;
}

int main(){
    int m,n;
    scanf("%d%d",&n,&m);//n是结点个数,m是边的个数
    int *father=(int *)malloc(sizeof(int)*(n+1));

    for (int i=0;i<n+1;i++) father[i]=i;

    for(int i=0;i<m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        join(x,y,father);
    }

    int source,destination;
    scanf("%d%d",&source,&destination);

    printf("%d",issame(source,destination,father));

    return 0;
}


http://www.kler.cn/news/283593.html

相关文章:

  • 计算机毕业设计选题推荐-摇滚音乐鉴赏网站-Java/Python项目实战
  • 第2章-05-接口API与安全签名算法
  • 网络安全售前入门03——审计类产品了解
  • 【提分必看!】蓝桥杯单片机提分技巧(国一经验分享)
  • phpstorm远程连接阿里云项目
  • 第 8 章 数据的家——MySQL的数据目录
  • 如何使用查询路由构建更先进的 RAG
  • 绕过后端校验的策略
  • 关于el-table的show-summary,合计栏不显示以及保留两位小数问题
  • Quarkus 后端开发记录
  • matlab 采样的非周期性矩形
  • 在野漏洞的应急响应流程
  • 【drools】kie:官方仓库clone 遇到问题解决
  • 利用API接口实现商品信息自动化更新的高效策略
  • centos基础设置
  • 【面试经验】字节商业产品日常实习面经
  • MySQL给用户授权
  • k8S Deployment
  • 计算机毕业设计选题推荐-汽车租赁系统-Java/Python项目实战
  • 整理了几十家高频面试题,让你避坑软件测试公司面试的套路,收藏收藏刷起来...
  • 「OC」CAlayer——巧用动画实现一个丝滑的折叠cell
  • 云端集中管控边缘服务:利用 EMQX ECP 在 K8s 上快速部署 NeuronEX
  • 删除微信重复文件的简易工具
  • unreal engine5中character角色和怪物交互时发生穿模
  • Kubernetes存储Volume
  • 借题《黑神话悟空》,聊聊UE5 游戏开发中基本的 C++ 概念
  • 日常刷题(24)
  • 【为项目做准备】Linux操作系统day1
  • STM32G474采用“多个单通道ADC转换”读取3个ADC引脚的电压
  • 报错:E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。