首页 > 其他分享 >并查集——AcWing 239. 奇偶游戏

并查集——AcWing 239. 奇偶游戏

时间:2024-07-14 15:26:23浏览次数:11  
标签:奇偶 int 查集 查找 239 集合 节点

目录

并查集

定义

运用情况

注意事项

解题思路

AcWing 239. 奇偶游戏

题目描述

运行代码

代码思路

改进思路

并查集

定义

并查集(Disjoint Set Union,简称DSU),是一种树形的数据结构,常用于处理一些不交集的合并及查询问题。在并查集中,元素被分成多个不相交的集合,每个集合由一个代表元素表示,通过一系列的合并(Union)和查找(Find)操作来维护这些集合的状态。

运用情况

  1. 连通性问题:判断两个元素是否属于同一个集合,常用于图的连通分量问题。
  2. 动态连接问题:在元素集合之间建立连接,同时保持快速查询元素间的连接状态。
  3. 最小生成树:Kruskal算法中用于检测边加入后是否形成环路。
  4. 游戏算法:如迷宫生成、棋盘类游戏等,判断区域的联通性。

注意事项

  1. 路径压缩:为了提高查找效率,可以使用路径压缩技术,使得每次查找后路径上的所有节点都直接指向根节点。
  2. 按秩合并:在合并两个集合时,将秩较小的集合的根节点作为较大集合的子节点,可以保持树的平衡,降低树的高度,从而加快查找速度。
  3. 内存管理:并查集的数组通常会占用较大的空间,需要合理规划内存使用,特别是在大规模数据处理中。

解题思路

  1. 初始化:为每个元素创建一个单独的集合,并且每个元素都是其所在集合的根节点。
  2. 查找(Find):找到某个元素所在集合的代表元素,一般使用递归或迭代实现。
  3. 合并(Union):将两个集合合并成一个集合,通常选择一个集合的根节点作为新集合的根节点。

AcWing 239. 奇偶游戏

题目描述

239. 奇偶游戏 - AcWing题库

运行代码

#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;

const int N = 20010;

int n, m;
int p[N], d[N];
unordered_map<int, int> S;

int get(int x)
{
    if (S.count(x) == 0) S[x] = ++ n;
    return S[x];
}

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

int main()
{
    cin >> n >> m;
    n = 0;

    for (int i = 0; i < N; i ++ ) p[i] = i;

    int res = m;
    for (int i = 1; i <= m; i ++ )
    {
        int a, b;
        string type;
        cin >> a >> b >> type;
        a = get(a - 1), b = get(b);

        int t = 0;
        if (type == "odd") t = 1;

        int pa = find(a), pb = find(b);
        if (pa == pb)
        {
            if (d[a] ^ d[b] != t)
            {
                res = i - 1;
                break;
            }
        }
        else
        {
            p[pa] = pb;
            d[pa] = d[a] ^ d[b] ^ t;
        }
    }

    cout << res << endl;

    return 0;
}

代码思路

  1. 初始化

    • 使用 unordered_map 存储每个节点映射到的唯一ID,这样可以处理任意数量的节点,而不仅仅是从0开始编号的连续整数。
    • n 和 m 分别代表节点的数量和边的数量,但实际中 n 在运行时动态增加。
    • 每个节点的父节点 p[i] 初始化为其自身,表示它们各自构成独立的集合。
    • d[i] 数组存储从节点 i 到其根节点路径上的“奇偶”属性,初始值为0。
  2. 读取输入

    • 读取边的数量 m 和节点间的连接信息。
    • 对于每条边,获取或分配节点的ID,读取边的类型(奇数或偶数)。
  3. 并查集操作

    • 对于每条边,检查两个节点是否已经在同一集合中,如果是,则检查它们之间的“奇偶”属性是否符合当前边的类型。
    • 如果不符合,则提前终止并输出矛盾发生的边序号减一。
    • 如果两个节点不在同一集合中,执行合并操作,更新父节点和“奇偶”属性。
  4. 输出结果:输出最后一次有效的边序号或者如果发现矛盾则输出矛盾前的边序号。

改进思路

  1. 减少哈希查找:目前 get 函数每次都会检查 unordered_map 是否包含键,这会导致额外的时间开销。可以通过预处理所有节点的映射,减少运行时的哈希查找次数。

  2. 空间优化unordered_map 在最坏情况下可能导致较高的空间开销。如果节点编号是连续的,可以考虑使用线性数组代替哈希表。

  3. 并查集优化:虽然代码中没有明确展示,但可以通过按秩合并和路径压缩来进一步优化并查集的性能。

  4. 预处理节点映射:在读取边之前,先读取所有节点,为它们分配ID,并存储在一个数组中,之后不再使用 unordered_map

  5. 空间优化:如果节点编号是连续的,使用数组替代 unordered_map 来存储节点ID映射。

  6. 并查集性能改进:在 find 函数中添加路径压缩逻辑,确保每次查找后路径上的所有节点都直接指向根节点,这可以显著减少未来查找的深度。

标签:奇偶,int,查集,查找,239,集合,节点
From: https://blog.csdn.net/u014114223/article/details/140406313

相关文章

  • 定积分之奇偶函数公式
    brief若\(f(x)\)在\([-a,a]\)上连续且为偶函数,则:\[\int_{-a}^{a}f(x)dx=2\int_{0}^{a}f(x)dx\]若\(f(x)\)在\([-a,a]\)上连续且为奇函数,则:\[\int_{-a}^{a}f(x)dx=0\]proveinvoke:定积分的性质Part0\[\begin{align}根据定积分的性质2:\\\int_{-a}^{a}f(x......
  • 24暑假算法刷题 | Day11 | LeetCode 150. 逆波兰表达式求值,239. 滑动窗口最大值,347.
    目录150.逆波兰表达式求值题目描述题解239.滑动窗口最大值题目描述题解347.前K个高频元素题目描述题解150.逆波兰表达式求值点此跳转题目链接题目描述给你一个字符串数组tokens,表示一个根据逆波兰表示法表示的算术表达式。请你计算该表达式。返回一个......
  • 并查集的学习及运用
    1.定义在看并查集之前,我们先来看一下并查集是什么:并查集是一种用于管理元素所属集合的数据结构。它也有很多用途:在无向图中找环、判断连个元素是不是一个集合等等,所以用起来也十分方便,代码也很短2.模板intfind(intk){ if(vec[k]==k)returnk;//判断自己还有没有祖先 e......
  • P2398 GCD SUM
    原题链接题解\(ans=\sum_{i=1}^{n}i*sum[i]\)其中\(sum[i]\)为最大公约数为\(i\)的对数令\(f[i]\)为最大公约数为\(i\)的倍数的对数则有\(sum[i]=f[i]-sum[2i]-sum[3i]-...-sum[ki]\)而\(f[i]={\lfloor\frac{n}{i}\rfloor}^2\)(如果没懂请仔细阅读题目所给符号......
  • 数据结构——并查集 学习笔记
    数据结构——并查集学习笔记并查集是一种用于管理元素所属集合的数据结构,实现为一个森林。并查集中,每棵树表示一个集合,树中的节点表示对应集合中的元素。其思想是,把集合属性绑定到根节点上,避免多余的处理,因此一般难以分离。普通并查集并查集支持两种操作:合并(Union):合并两个元素......
  • 并查集
    <2024.7.9>基本概念:主要用于解决一些元素分组的问题。它管理一系列不相交的集合,并支持两种操作:合并(Union):把两个不相交的集合合并为一个集合。查询(Find):查询两个元素是否在同一个集合中使用步骤:初始化,假设每个人指向自己根据每个人的意向确定边的连接选出一个集合的代......
  • 并查集扩展应用
    并查集扩展应用A.货物运输题目描述有\(n\)座城市和\(m\)条双向道路。已知走过每条边所需要的汽油量,\(q\)次询问,求汽油量为\(l\)的车可以在多少对城市之间运送货物。(汽车到达城市会立刻把油全部加满)题解这道题没有强制在线,所以可以考虑进行离线。对于大小为\(n\)一......
  • P2239 [NOIP2014 普及组] 螺旋矩阵
    洛谷题面:题目分析本题需要一个旋转的数字矩阵,因为填数要求,首先考虑DFS。注意写题目时,一定一定要注意数据范围!在此题中,注意数据范围对于 50%的数据,1⩽......
  • HT-014 Div3 跳棋 题解 [ 黄 ] [ 并查集 ] [ 树型结构 ]
    分析依旧是一个连通块题。观察题面不难发现两个重要性质:一个跳棋只能以它旁边的两个跳棋为中点跳跃,且满足跳跃路线中除中点以外没有其它跳棋阻挡。只有我们的跳棋可以移动。跳棋的操作具有可逆性/对称性。第三条性质可以这么理解,就是一个跳棋跳过去之后,它还可以跳回来。......
  • 【并查集】浅谈思想 & 代码实现 & 实战例题(C/C++)
    思想综述并查集(Union-Find)算法的主要操作包括两种:合并(Union):将两个不相交的集合合并成一个集合。查询(Find):查询两个元素是否属于同一个集合。并查集算法的核心思想是使用树(通常是森林)来表示这些不相交的集合,其中每个集合被表示为一棵树,树的根节点代表这个集合的标识(或称为代表......