首页 > 其他分享 >边权并查集之奇偶游戏

边权并查集之奇偶游戏

时间:2024-04-25 20:58:33浏览次数:25  
标签:奇偶 py int 边权 查集 fa 压缩 px 节点

题目传送门:https://www.acwing.com/problem/content/241/
//懒得手敲题目

先给一下题解:

#include<iostream>
#include<unordered_map>
//这个题目有两个点要想明白,一个是点到根的距离标志着这个点的性质,且在路径压缩的过程中此点不会改变
//第二点就是在出现新的关系,也就是要将两个集合合并到一起的时候,一个点到根的距离是偶数表示是同性的,可能是同奇或者同偶
//合并的时候,
using namespace std;

const int N=1000010;
int fa[N],d[N];
unordered_map<int,int>s;
int n,m;
int find(int x)
{
    if(fa[x]==x) return fa[x];
    else{
        int px=find(fa[x]);
        d[x]+=d[fa[x]]; //px是已经被更新过的值,不可用fa[x]去更新
        fa[x]=px;
    }
    return fa[x];
}
int get(int x)
{
    if(!s.count(x)) s[x]=++n;
    return s[x];
}

int main()
{
    cin>>m>>m;
    n=0;
     int l,r,t,res; string s;
     for(int i=1;i<N;i++) fa[i]=i;  
     
     for(int i=1;i<=m;i++)
     {
        cin>>l>>r>>s;
        if(s=="even") t=0;
        else t=1;
        //直接判断信息之前是不是已经给出了
        int x=get(l-1),y=get(r);
        int px=find(x),py=find(y); //d[x]+?+d[y]=t
        if(px!=py)
        {
            fa[px]=py;
            d[px]=abs(d[x]-d[y]-t);
        }else
        {
            if(abs(d[x]-d[y])%2!=t)
             {res=i-1;
             break;}  //找到直接返回
        } 
     }
    
    cout<<res<<endl;
}

最近一直在做并查集的题目,有些问题困扰许久,故在此以此题为契机来回答一下几个疑惑点。
(1)第一点:路径压缩的时候,修改点的边权究竟是+=d[rx]还是+=d[fa[x]]?
图中也给出了解释,是+=d[fa[x]],因为递归得到的根结点,而d[fa[x]]表示父节点到根节点的距离,加上根节点的距离是没有意义的。所以是加上父节点到根节点的距离再去将父节点修改为根节点。
(2)类似于此的并查集中先看所给的值是否又同一个根节点是何含义呢?
这里就是已经给出的条件我一定是放到了同一个集合里面,只是每个点到根节点的距离不同,以此来维护各个点所在的群。像这个题目就是两个群。而食物链就是三个群。
最重要的一点是,矛盾一定产生于已经给出的条件,也就是已有的一个集合。新给出的条件暂时无法判断,直接就放到了集合里面。

还有就是这个题目简化了多种情况,使得代码非常简洁,但同时也非常难理解。

关于此题,我也些问题:
(1)路径压缩为何不会改变每个点到根节点的奇偶性呢?
在图中给出解释,假如这个时候要查询4的祖先。那么就要路径压缩,同时假如之前的点都没有过路径压缩。可以看出每个点此时维护的都只是和父亲结点的奇偶性,而在路径压缩之后,就是对根节点(此时也就是每个结点的父节点)的奇偶性质(图中未给出)。比方说,假如1是奇,2到它的距离为1,所以2是偶数,3在路径压缩之前是偶数(到2的距离是2),3作完路径压缩之后到1的距离是3,与压缩之前和1结点的奇偶性是一致的。以此类推。这点也困扰我许久,因为暂时还未看异或处理的压缩方法。
(2)合并集合是怎么计算距离的?
这里我就懒得画图,直接想象吧。假如x的根节点是px,y的根节点是py,然后要将px指向py,同时计算px到py新的距离。
这里的t表示x和y是否是同奇偶性质的,如果是0表示同奇或者同偶,如若是1,则一为奇一为偶。
(d[x]+?+d[y])%2==t
这里很神奇,因为这个数随便是啥都行。d[x]-d[y]-t,-+随意组合答案都是对的(加绝对值)。
这是为什么呢?一方面我觉得可能什模2的特殊性(食物链绝无此性质),一方面所有情况也确实都包含进去了。
d[x]为奇数,d[y]为奇数,t=0 或者1 ,一共有八种组合,也的确八种情况都是对的,简直神奇!!
不过严格来讲,还是食物链的推法更合理且适用。

标签:奇偶,py,int,边权,查集,fa,压缩,px,节点
From: https://www.cnblogs.com/wl511/p/18158485

相关文章

  • [算法学习笔记] 并查集
    提示:本文并非并查集模板讲解,是在模板基础上的进一步理解以及拓展。Review并查集可以用来维护集合问题。例如,已知\(a,b\)同属一个集合,\(b,c\)同属一个集合。那么\(a,b,c\)都属一个集合。并查集分为合并,查询操作。定义\(fa_i\)表示点\(i\)的父亲。为了降低复杂度,在fi......
  • 并查集
    1.0并查集概念对于具有传递性质、联通集合的题目可以考虑并查集。1.1并查集模板声明:以下模板来自于https://xuq7bkgch1.feishu.cn/docx/CAbedNJ5KobvinxdyKgcKsrlnrd。有n个数,编号是1~n,最开始每个数各自在一个集合中,现在要进行m个操作,操作共有两种:1.Mab,将编号为a......
  • 528. 奶酪(并查集orBFS)
    题面如下:https://www.acwing.com/problem/content/530/大致思路是:合并所有连接的空洞,判断下表面的空洞和上表面的空洞是否是同一集合集合#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>usingnamespacestd;constintN......
  • 倍增并查集
    如果你既会倍增,又会并查集,那你一定会倍增并查集吧!link数据范围明示\(O(n^2)\)无法通过。众所周知,倍增是\(O(\logn)\)的,并查集近似\(O(n)\)的,它们结合一下不就能过了吗?先来重新考虑一下倍增的本质。倍增倍增最经典的用法是ST表。我们将一个区间拆成两个长为\(2^k\)......
  • 928. 尽量减少恶意软件的传播 II【并查集加暴力删边判断】
    题意不是很清晰:1.比如对于graph=[[1,1,0],[1,1,1],[0,1,1]],initial=[0,1]来说,可以发现结点的链接情况是0-1-2,感染源结点是0和1,若是按之前题目的要求,移除0和1都不会减少最终感染个数,但是应该返回结点0,因为其index小。但是应用此题的条件,就一定要返回结点1,因为移除结点1之......
  • P3295 [SCOI2016] 萌萌哒(倍增并查集)
    题意简述有一个长为\(n\)的数字序列\(s\),有\(q\)组限制\(l_1,r_1,l_2,r_2\)形如\(s_{l_1,\cdots,r_1}=s_{l_2\cdots,r_2}\),求满足所有限制的\(s\)的方案数,数字序列不能有前导0。\(n,q\le10^5\),保证\([l_1,r_1]\)和\([l_2,r_2]\)大小相等。分析字符之间的等量......
  • Golang交替打印奇偶数
    packagemainimport( "fmt" "sync")varwgsync.WaitGroupfuncmain(){ evenCh,oddCh:=make(chanbool,1),make(chanbool,1) deferclose(evenCh) deferclose(oddCh) wg=sync.WaitGroup{} wg.Add(1) goprintNumbersSequent......
  • 2019年蓝桥杯省赛-修改数组(并查集)
    0.题目时间限制:1.0s内存限制:256.0MB本题总分:20分【问题描述】给定一个长度为N的数组A=[A1,A2,···AN],数组中有可能有重复出现的整数。现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改A2,A3,···,AN。当修改Ai时,小明会检查......
  • 蓝桥杯-并查集-合根植物
    0.题目1.解析1.1并查集思路主要三大模板功能1.初始化(init)2.寻找父节点(find)3.合并(merge)我们在find中可以使用路径压缩简化运算,缩短运行时间而启发式合并则可以将运行时间压缩,由O(n)到o(logn)代码#include<bits/stdc++.h>usingnamespacestd;constintMaxn......
  • 并查集
    介绍并查集主要用于处理一些不相交集合的合并问题,一些常见的用途有求联通子图,求最小生成树的Kruskal算法和求最近公共祖先等。并查集的基本操作主要有:初始化查询合并操作初始化假设有编号为1,2,3……,n的n个元素,我们用一个数组fa[]来储存每个元素的父节点。一开始,我们先将......