并查集

并查集

喜你入骨 提交于 2019-11-28 01:32:38
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int fa[10003]; 5 int n , m; 6 int getf(int p) 7 { 8 if(fa[p] == p) 9 return p; 10 return fa[p] = getf(fa[p]); 11 } 12 int merge(int x , int y) 13 { 14 int t1 = getf(x) , t2 = getf(y); 15 if(t1 == t2) 16 return 0; 17 fa[t1] = t2; 18 return 1; 19 } 20 int main() 21 { 22 int opt , x , y; 23 scanf("%d%d" , &n , &m); 24 for(int i = 1; i <= n; i++) 25 fa[i] = i; 26 for(int i = 1; i <= m; i++) 27 { 28 scanf("%d%d%d" , &opt , &x , &y); 29 if(opt == 1) 30 merge(x , y); 31 if(opt == 2) 32 { 33 if(getf(x) == getf(y)) 34 printf("Y\n"); 35

经典模型——并查集解决区间/树链染色问题

旧巷老猫 提交于 2019-11-28 00:46:20
蒟蒻的第一篇blog 模型背景: 已知一个长度为n的序列,开始时序列的每一个元素都没有颜色(0),现进行m次操作,第i次操作将一段区间[l,r]中 还未被染色的点 (即a[i]=0的点)染成颜色i.问m次操作后这个区间长什么样子,并将它输出来. 数据规模约定:对于100%的数据,n,m<=10^6 问题解决 我会nm暴力! 对于每一个操作i,暴力扫描[l,r],染色,最后输出. ※期望得分:10. 并查集! 没想到吧 用并查集来维护从节点i往后的区间[i,n]中第一个0出现的位置,也就是i之后第一个还未被染色的点的位置. 这是怎么做到的呢? 一开始每个节点的father显然指向自己(所有点都没染色).如果这个点被染了色,就将它与它的右边第一个点union起来,即father[i] = father[i+1]. 比如: 经过几次之后的染色以及一番奇妙的路径压缩,序列将形成类似这种样子 这样,不就给下一次的操作省时间了吗,不就能一跳就跳到下一个0的地方染色了吗(欣喜) 核心代码: int findfather(int x) {//找下一个为0的点,顺便路径压缩 if (father[x] != x) father[x] = findfather(father[x]); return father[x]; } inline int combine(int x, int y) {/

数据结构小结

会有一股神秘感。 提交于 2019-11-27 23:53:43
并查集 普通的并查集没有什么好说的,对于遇到的题目,我们主要是要把它抽象成并查集的模型,比如 萌萌哒 这道题就是一个对于模型的抽象,相同的标记其实就是一个并查集。 然后想说一下并查集的两种合并,一种是路径压缩,一种是按秩合并。 按秩合并更多是对于可撤销并查集 (还没打过板子) 和 可持久化并查集 然后个人觉得有一个很重要的思想就是镜像点思想,关押罪犯和 Uva 11987 都是这种思想 带权并查集目前只见过搬砖(bricks)那道题。 线段树 基操没有什么好说的了 线段树主要是用来维护区间信息,是一个很好的工具。 也常常用来优化时间。(比如 线段树优化dp ) 打标记 //为什么在Pushdown中更新下面的总值的时候为什么不把要更新的点的Pass也加进去, //是因为在modify的时候我已经用他原来的Pass值更新过一遍了,当然不需要加进去 //即:标记下传给左右儿子时答案(比如sum)是用k的来更新,而不是k<<1和k<<1|1 加标记和乘标记 加标记:打上就行 乘标记:加标记乘上这个值,乘标记打上 pushdown: 先乘再加 加标记和赋值标记 加标记:打上就行 赋值标记:加标记去掉,打上赋值标记 pushdown: 先放赋值标记,再放加标记 翻转标记 多是在splay上面打。 但翻转标记和赋值标记加标记不冲突。 打标记基础题 戳 打标记妙题 戳 树链剖分 也是一个工具

UVa 11987(并查集)

不打扰是莪最后的温柔 提交于 2019-11-27 23:47:53
传送门 镜像点思路 具体见 这篇博客 i的信息存在i'里在2操作时就不会有影响 #include<bits/stdc++.h> #define N 200003 using namespace std; int read() { int x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } int fa[N],num[N],sum[N]; void init(int n) { for(int i=1;i<=n;++i) { fa[i]=i+n;fa[i+n]=i+n; sum[i+n]=i;num[i+n]=1; } } int get(int x) { if(fa[x]==x)return x; return fa[x]=get(fa[x]); } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { init(n); for(int i=1;i<=m;++i) { int op=read(); if(op==1) { int p=read(),q=read(); int f1=get(p),f2=get

noip模拟测试 主仆见证了 Hobo 的离别

南楼画角 提交于 2019-11-27 22:08:57
考试想到了正解然而并没有什么卵用(当然不是dfs) 做法稍有不同我用的是并查集 因为这题比较容易看出来并查集大概可做 考虑并查集特点:只能查询总父亲,判断是否在一个集合内; 那么我们只能离线来做。否则只能判断集合不能判断父子关系 考虑正确性:发现并和交没有关系(就算有关系对于某个点来说我们也只会可能是同级关系不会产生父子关系),这样我们可以分开 用两种并查集一种维护并操作另一种交操作。 我们只在新加入这个点(即它合成时处理和它相关操作即可),对于询问x,y; 我们处理两个里比较大的 : y大说明它是并出来的(假设它是因为被合并当了父亲的话就不是最大的了),说明我们在并的并查集中去解决它即可; 同理:x大说明它是交出来的,我们放入交中的query去解决,注意的是要翻转一下并查集中的父子关系,使交出来的儿子去当集合中的父亲。。。 K=1,合同交,我们在并和交的离线操作中均去解决保证他们都当了一次另一个节点的父亲。。。 复杂度因为最多把用来融合的元素都扫了一遍,并查集查一次大概是logn的 所以大概是o(2*n+nlogn)的或者与M有关大概是这个样子总之复杂度不会超掉 来源: https://www.cnblogs.com/three-D/p/11379823.html

hdu 1811 并查集+拓扑排序+细心

流过昼夜 提交于 2019-11-27 21:30:23
Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球。 为了更好的符合那些爱好者的喜好,Lele又想了一个新点子:他将制作一个全球Tetris高手排行榜,定时更新,名堂要比福布斯富豪榜还响。关于如何排名,这个不用说都知道是根据Rating从高到低来排,如果两个人具有相同的Rating,那就按这几个人的RP从高到低来排。 终于,Lele要开始行动了,对N个人进行排名。为了方便起见,每个人都已经被编号,分别从0到N-1,并且编号越大,RP就越高。 同时Lele从狗仔队里取得一些(M个)关于Rating的信息。这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B,等于B,小于B。 现在Lele并不是让你来帮他制作这个高手榜,他只是想知道,根据这些信息是否能够确定出这个高手榜,是的话就输出"OK"。否则就请你判断出错的原因,到底是因为信息不完全(输出"UNCERTAIN"),还是因为这些信息中包含冲突(输出"CONFLICT")。 注意,如果信息中同时包含冲突且信息不完全,就输出"CONFLICT"。 Input 本题目包含多组测试,请处理到文件结束。 每组测试第一行包含两个整数N,M(0<=N<=10000,0<=M<=20000)

考后反思8.19

社会主义新天地 提交于 2019-11-27 21:08:45
水题再次没切掉 好吧不算水 t1做过一个类似的,然而我不会判重 我$<=10$没对然而我$Ai$互不相同(应该是)对了,我是真不会判重,然而我大体思路找gcd对了 然而用set非常轻松帮你判重 $t2$像是水题 我一开始想并查集,然而一个普通并查集很难维护,于是我就考虑了拓展域,一个并查集很难维护于是我开了两个并查集 然后发现根本不用那么麻烦,暴力建边跑dfs就行,非常简单, 一定要学会分析复杂度 拿这个举个例子 新元件的编号等于融合之前元件的总个数加一 。当然,参与融合的 K个元件融合之后依然存在,并且 每个元件至多参与一次融合 。 分析最多$20$层左右,直接$dfs$最差复杂$log$(两两不重合并) $t3$dp优化,遗憾的是$qj$错了少了$10$分 来源: https://www.cnblogs.com/znsbc-13/p/11376809.html

LCA详解

a 夏天 提交于 2019-11-27 21:02:14
LCA,即最近公共祖先,在图论中应用比较广泛。 LCA的定义如下:给定一个有根树,若节点$z$同时是节点$x$和节点$y$的祖先,则称$z$是$x,y$的公共祖先;在$x,y$的所有公共祖先当中深度最大的称为$x,y$的最近公共祖先。下面给出三个最近公共祖先的例子: 显然,从上面的例子可以得出,$LCA(x,y)$即为$x,y$到根节点的路径的交汇点,也是$x$到$y$的路径上深度最小的节点。 求LCA的方法通常有三种: 向上标记法 树上倍增法 Tarjan算法 当然,求LCA还有其它方法,例如树剖等,请读者自行了解,本文主要讲解上面提到的三种方法。 向上标记法 向上标记法是求LCA最直接的方法,直接根据定义来求,单次查询的时间复杂度最坏为$O(n)$ (看起来好像还挺快的,不过什么题会只有一次查询呢) 算法流程: 从x节点向上一直走到根节点,沿途标记经过的节点 从y节点向上一直走到根节点,当第一次遇到已标记的节点时,该节点就是$LCA(x,y)$ 该方法思想是绝对简单的,实现也简单,因此在这里就不给出具体实现了。不过由于其时间复杂度过高,在实际中基本不会应用到,在这里提一下主要还是为讲解Tarjan算法做基础。 树上倍增法 树上倍增法应用非常广泛,读者可以深入地学习。用树上倍增法求LCA的时间复杂度为$O((n+m)logn)$。 树上倍增法用到了二进制拆分的思想。在求LCA时

Is It A Tree? POJ - 1308(并查集判树)

穿精又带淫゛_ 提交于 2019-11-27 20:35:55
Problem Description A tree is a well-known data structure that is either empty (null, void, nothing) or is a set of one or more nodes connected by directed edges between nodes satisfying the following properties. There is exactly one node, called the root, to which no directed edges point. Every node except the root has exactly one edge pointing to it. There is a unique sequence of directed edges from the root to each node. For example, consider the illustrations below, in which nodes are represented by circles and edges are represented by lines with arrowheads. The first two of these are

POJ 1611 ---The Suspects(并查集)

巧了我就是萌 提交于 2019-11-27 20:33:02
Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. To minimize transmission to others, the best strategy is to separate the suspects from others. In the Not-Spreading-Your-Sickness University (NSYSU), there are many student groups. Students in the same group intercommunicate with each other frequently, and a student may join several groups. To prevent the possible transmissions of SARS, the NSYSU collects the member lists of all student groups, and makes the following rule in their standard operation