种类并查集学习笔记&例题

一、种类并查集

当我们要维护朋友的朋友是朋友,敌人的敌人也是朋友的关系时,最朴素的做法是开两个并查集数组,写两个不同的find和merge函数,分别存敌人和朋友,但这样显然是比较麻烦。于是,我们可以将并查集开为平常大小的两倍,前一半用于维护一种关系,另一半用于维护另一种关系。假设B是A的敌人,那么合并(A+n)和B即可。

二、例题

题目: https://www.luogu.com.cn/problem/AT_abc327_d

思路:这题就是典型的种类并查集,一个数不是0就是1,所以与0相对的是1,与0相对再相对就还是0,可以利用种类并查集维护这样的关系,详见代码。

以下是ac代码(附带详细注释)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define lop(i,a,b) for(int i=(a);i<(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define el 'n' 
typedef pair<int,int> PII;
using LL = long long;
const int INF=0x3f3f3f3f;
const int N=2e5+10;
int n,m;
int a[N],b[N];
int f[N*2];
int find(int x)//并查集找老大板子
{
    return x==f[x]?x:f[x]=find(f[x]);
}
void solve()
{
    cin>>n>>m;
    rep(i,1,n*2)f[i]=i;//初始化
    rep(i,1,m)cin>>a[i];
    rep(i,1,m)cin>>b[i];
    rep(i,1,m)
    {
        if(find(a[i])==find(b[i]))//都在前一半说明二者相等,与题目矛盾
        {
            cout<<"No";
            return;
        }
        f[find(a[i]+n)]=find(b[i]);//否则分别把后一半(意味着敌人的)与另一个合并
        f[find(n+b[i])]=find(a[i]);
    }
    cout<<"Yes";
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t = 1;
    //cin>>t;
    while(t--)
      solve();
    return 0;
}
相关推荐
智者知已应修善业2 分钟前
【无序数组指针交换2则】2024-10-28
c语言·数据结构·c++·经验分享·笔记·算法
Wcbddd3 分钟前
OpenClaw+思源笔记=自动撰写渗透报告的牛马
笔记
一叶落4383 分钟前
LeetCode 136. 只出现一次的数字(C语言详解 | 哈希表 + 排序 + 位运算)
c语言·数据结构·算法·leetcode·哈希算法·散列表
古译汉书4 分钟前
【数据结构算法】二分查找
c语言·开发语言·数据结构·c++·算法
逆境不可逃6 分钟前
【从零入门23种设计模式19】行为型之观察者模式
java·开发语言·算法·观察者模式·leetcode·设计模式·动态规划
数图模方6 分钟前
大屏设计笔记 | 核心指标体系3(数据分析层)
笔记·物联网·产品经理·3d可视化·大屏端
小龙报7 分钟前
【算法通关指南:算法基础篇】二分答案专题:1.木材加工 2.砍树
c语言·数据结构·c++·算法·启发式算法
invicinble15 分钟前
学习视频的全域理解
学习
cici1587419 分钟前
经典的基于策略迭代和值迭代法的动态规划MATLAB实现
算法·matlab·动态规划
月明长歌20 分钟前
【码道初阶-Hot100】 LeetCode 49. 字母异位词分组:从排序哈希到分组映射,彻底讲透为什么排序后可以作为同一组的标识
算法·leetcode·哈希算法