IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【ACwing】二、 数据结构:836. 合并集合 837. 连通块中点的数量 240. 食物链 -> 正文阅读

[数据结构与算法]【ACwing】二、 数据结构:836. 合并集合 837. 连通块中点的数量 240. 食物链

836. 合并集合

https://www.acwing.com/problem/content/838/
请添加图片描述

# include<iostream>
using namespace std;
const int N = 100010;
int p[N];
int n,m;

int find(int x){ //查询x的根节点并返回 + 路径压缩
    if(p[x] != x) p[x] = find(p[x]); //在递归的路径中只要x不是根节点,就将p[x]设置为父节点的根节点
    return p[x];
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++) p[i]=i;
    
    while(m--){
        char op[2];
        int a,b;
        scanf("%s%d%d",op,&a,&b);
        if(op[0]=='M') p[find(a)] = find(b); //设置a的根节点的父节点 为 b的根节点
        else{ //查询是否在同一集合中
            if(find(a)==find(b)) puts("Yes");
            else puts("No");
        }
    }
    
}

837. 连通块中点的数量

https://www.acwing.com/problem/content/839/
在这里插入图片描述
此题中的n个点在添加了边后,会形成多个连通图,每个连通图可以看做一个集合。查询两个点是否在一个连通块中等价于查询两个数是否在同一集合。所以可以使用并查集来解决,并查集的功能:1、将两个集合以近似O(1)的复杂度进行合并 2、询问两个元素是否在一个集合中。

具体如下:

  • 把根节点作为集合的标号,在a、b之间添加一条边就等价于将两个集合合并,等价于将a所在树的根的节点即find(a) 设为 b所在树的根即find(b),使a所在树 变成 b所在树的子树。同时为了求取第三个问题,要设置一个数组capacity记录每个连通图的点数 即 每个集合的元素数(通过各个树的根确定集合),在合并时如果两个点属于不同的集合则合并后的capacity[rootB]为capacity[rootB]+capacity[rootA]
  • 查询两个点是否在同一连通块中,等价于查询两个数的集合编号是否相等(是否属于同一个根)
  • 询问a所在连通块的数量,等价于求capacity[find(a)]
# include <iostream>
using namespace std;
const int N = 100010;

int p[N],capacity[N];
int n,m;

int find(int x) {
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++){
        p[i] = i;
        capacity[i] = 1; //初始每个点都是一个单独的连通图,集合大小为1 
    }
    
    while(m--){
        int a, b;
        char op[5];  
        scanf("%s", op); //输入操作
        
        if(op[0] == 'C') { //合并
            scanf("%d%d", &a, &b);
            if(find(a) != find(b)) //只有两个数不属于同一连通块时才更新连通块内点数
            	capacity[find(b)] += capacity[find(a)]; 
            p[find(a)] = find(b);
        }else if(op[1] == '1') { // 查询ab是否在同一集合
            scanf("%d%d",&a,&b);
            if(find(a) == find(b)) puts("Yes");
            else puts("No");
        }else { // 查询a所在的连通块中的点数
            scanf("%d",&a);
            printf("%d\n",capacity[find(a)]);
        }
    }
    return 0;
}

240. 食物链

https://www.acwing.com/problem/content/242/
在这里插入图片描述
请添加图片描述

# include <iostream>
using namespace std;
const int N = 50010;
int p[N],d[N]; 
int n,k,res;

int find(int x){
    if(p[x] != x) {
        int tmp = find(p[x]); //记录根
        d[x] += d[p[x]]; //在回溯的时候d会更新
        p[x] = tmp; //父节点都更新为根节点 
    }
    return p[x];
}

int main(){
    cin>>n>>k;
    for(int i = 1; i <= n; i++){
        p[i] = i; //初始每个点自为一个集合,到父节点的距离为0,而d默认都赋为了0
    }
    while(k--){
        int t,x,y;
        cin>>t>>x>>y;
        if(x > n || y > n)  res++;
        else if(t==1){ //同类
            int rootX = find(x), rootY = find(y);
            if(rootX == rootY && (d[x] - d[y]) % 3 != 0)  res ++;
                
            else if(rootX != rootY) { //不在一个集合,但又是同类,所以将其合并
                p[rootX] = rootY; //将x树作为子树插入y树
                d[rootX] = d[y] - d[x]; //更新rootX到根的距离
            }
        }else { //x吃y
            int rootX = find(x), rootY = find(y);
            if(rootX == rootY && (d[x] - d[y] - 1) % 3 != 0) res ++; //x取余后 不在 y取余后的下一位,则错误
            else if(rootX != rootY) { //不在一个集合,但存在吃的关系,所以将其合并
                p[rootX] = rootY; //将x树作为子树插入y树
                d[rootX] = d[y] + 1 - d[x] ; //更新rootX到根的距离
            }
        }
        
    }
    cout<<res<<endl;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 12:01:51  更:2022-04-26 12:02:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:35:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码