并查集

so easy(unordered_map+并查集)

与世无争的帅哥 提交于 2019-12-03 15:06:04
There are n n points in an array with index from 1 1 to n n, and there are two operations to those points. 1: 1 \ x 1 x marking the point x x is not available 2: 2 \ x 2 x query for the index of the first available point after that point (including x x itself) . 样例输入 5 3 1 2 2 2 2 1 样例输出 3 1 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 unordered_map<int, int> fa; 6 7 int findfa(int x) 8 { 9 if (!fa.count(x)) return x; 10 return fa[x] = findfa(fa[x]); 11 } 12 13 int main() 14 { 15 int n, q; 16 int op, x; 17 scanf("%d %d", &n, &q); 18 while (q--) 19 { 20 scanf("%d %d", &op, &x); 21 if

11.04Test

て烟熏妆下的殇ゞ 提交于 2019-12-03 11:40:56
11.04Test 查看请点个赞 转载请注明出处(~不然~) 题目 描述 做法 \(BSOJ5143\) 要求给 \(M\) 个通道染色,使得同色通道不能相交 转为矛盾模型, \(2-sat\) or二分图染色解决 \(BSOJ5145\) 多次加边,维护两点所在点双联通分量大小 \begin{cases}在线:LCT+并查集\离线:直接用并查集来"缩点"\end{cases} \(BSOJ4932\) 用 \(m\) 色染 \(n\) 格子:求染出结果方案数 以匹配数为状态设计 \(dp\) 再改设状态中点为色块 \(\text{Day1}\) \(T1\) n个天使排成一条直线,某些天使之间需要互相联系,他们之间的通讯可以通过黑白两种通道中的一种;所有通道必须在直线同侧(另一侧是地面);为了保证通讯效率,同种颜色的所有通道之间不能相交。请计算能否建立这种通讯方案。 转问题为矛盾模型:相交的两个区间颜色必须不同 因此用 \(2-sat\) 和二分图染色均可 注意图可以不连通 \(T2\) 在遥远的S星系中一共有N个星球,编号为1…N。其中的一些星球决定组成联盟,以方便相互间的交流。   但是,组成联盟的首要条件就是交通条件。初始时,在这N个星球间有M条太空隧道。每条太空隧道连接两个星球,使得它们能够相互到达。若两个星球属于同一个联盟,则必须存在一条环形线路经过这两个星球

并查集 【入门题】

自古美人都是妖i 提交于 2019-12-03 10:05:41
本人水平有限,题解不到为处,请多多谅解 本蒟蒻谢谢大家观看 题目 : 传送门 此题用 并查集 来解决是否是 连通 的问题 code: 1 #include<bits/stdc++.h> 2 #pragma GCC optimize(3) 3 const int N=4e6+10; 4 const int mod=998244353; 5 using namespace std; 6 int n,m,ans; 7 int fa[N]; 8 inline int read(){ 9 int x=0,f=1;char ch=getchar(); 10 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 11 while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 12 return x*f; 13 } 14 inline void write(int x) 15 { 16 if(x<0)x=-x,putchar('-'); 17 if(x>9)write(x/10); 18 putchar(x%10+'0'); 19 } 20 int find(int x){ 21 if(fa[x]==x)return x; 22 return fa[x]=find(fa[x]);/

[Gym-102346A] 偷偷偷 并查集处理图(坐标)

泪湿孤枕 提交于 2019-12-03 08:23:28
https://vjudge.net/problem/Gym-102346A 题意:判断监控器的范围能不能阻断左下角和右上角。 分析:利用并查集处理图,能连接起来的监控器合并起来,然后在最后标记每个集合能否连接到左下、右上、左右、上下的边界形成阻断。 注意: 每个集合可以用 find( x ) 到的祖先下标标记。 #include <bits/stdc++.h> using namespace std; const int maxn = 1e5+5; const int mod=998244353; int pre[maxn]; struct node{ int x,y,l; }s[maxn]; bool check(node a,node b){ return ( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) <= (a.l+b.l)*(a.l+b.l)); } int find(int x){ if(x!=pre[x]){ pre[x] = find(pre[x]); } return pre[x]; } void Union(int x,int y){ int rx=find(x),ry=find(y); if(find(x) != find(y)){ pre[rx] = ry; } } struct Node{ int x,y,a,b;

[NOI2001]食物链(并查集拓展域)&& [HAOI2006]旅行(Kruskal)

时光总嘲笑我的痴心妄想 提交于 2019-12-03 07:12:52
题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形。A 吃 B,B 吃 C,C 吃 A。 现有 N 个动物,以 1 - N 编号。每个动物都是 A,B,C 中的一种,但是我们并不知道 它到底是哪一种。 有人用两种说法对这 N 个动物所构成的食物链关系进行描述: 第一种说法是“1 X Y”,表示 X 和 Y 是同类。 第二种说法是“2 X Y”,表示 X 吃 Y 。 此人对 N 个动物,用上述两种说法,一句接一句地说出 K 句话,这 K 句话有的是真 的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。 • 当前的话与前面的某些真的话冲突,就是假话 • 当前的话中 X 或 Y 比 N 大,就是假话 • 当前的话表示 X 吃 X,就是假话 你的任务是根据给定的 N 和 K 句话,输出假话的总数。 输入格式 从 eat.in 中输入数据 第一行两个整数,N,K,表示有 N 个动物,K 句话。 第二行开始每行一句话(按照题目要求,见样例) 输出格式 输出到 eat.out 中 一行,一个整数,表示假话的总数。 emmmmm, 最近学了并查集, 并查集能维护连通性和传递性, 这道题假如单单用一个并查集来维护谁与谁是同类, 显然无法判断互相吃的情况, 那么就容易想到用三个并查集去维护, 我们把每个动物x拆成3个节点, 分别表示同类域, 捕食域,

cf 【并查集】

喜欢而已 提交于 2019-12-03 07:08:06
http://codeforces.com/contest/1245/problem/D 题意就是:你需要让所有城市都有电,你看也在该城市建电站使他有电,同时你可以链接他与其他城市,使之有电 解决: 我们可以吧每个城市自己建电站以及自己与其他城市的费用用结构体存起来,排个序,再用并查集连起来。 #include<bits/stdc++.h> #define numm ch-48 #define pd putchar(' ') #define pn putchar('\n') #define pb push_back #define debug(args...) cout<<#args<<"->"<<args<<endl #define bug cout<<"************" using namespace std; template <typename T> void read(T &res) { bool flag=false;char ch; while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true); for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm); flag&&(res=-res); } template <typename T> void

E - 食物链 (拆点并查集)

别等时光非礼了梦想. 提交于 2019-12-03 05:10:48
题目链接: https://vjudge.net/contest/339425#problem/E 思路: 这题原来做的时候用的是种类并查集,但是我忘了。 现在有一个更玄学的做法 因为说白了就是A B C 三个点之间的关系 那么我就把一个点拆成三个点(也就是开三倍的空间) 分别代表这个点是A B C 然后这个题就成了模拟??? 1 #include <math.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <iostream> 5 #include <algorithm> 6 #include <string> 7 #include <string.h> 8 #include <vector> 9 #include <map> 10 #include <stack> 11 #include <set> 12 //#include <random> 13 14 #define LL long long 15 #define INF 0x3f3f3f3f 16 #define ls nod<<1 17 #define rs (nod<<1)+1 18 const int maxn = 3e5 + 10; 19 const double eps = 1e-9; 20 int pre[maxn]; 21 22 void

并查集浅谈及其扁平化

狂风中的少年 提交于 2019-12-03 04:06:18
本人水平有限,题解不到为处,请多多谅解 本蒟蒻谢谢大家观看 并查集(普及基本知识) 1:目的 并查集的目的很容易理解,通俗点就是说你的亲戚的亲戚也是你的亲戚,用来检测任意两点是否同在一个集合内。 2:实现办法 实现的办法主要判断两点的最远公共祖先是否一样(亦就是两点所在的集合的根节点),我们可以定义一个fa[i]数组表示i的父亲,一开始所有点的父亲都是他自己(因为一开始每个点所代表的集合只有该店一个点而已,所以这个集合的根节点就是该点),随后会读进来几组数据,例如A B,则代表点A和点B是亲戚。则将fa[A]赋值为B或者将fa[B]赋值为A?显然是不对的,因为A和B的合并并不仅仅代表这两点,而是他们所在的集合。举个例子:你和一个女孩成了亲,那么原来她爷爷的奶奶的爷爷的奶奶的…以前和你没半毛钱关系,但是现在你爷爷的奶奶的爷爷的奶奶的…都和此人成为了亲戚,所代表的就是你和她的集合合并了。 3:合并点分别在的集合的根节点 可能听起来有些拗口,但实际上还是很容易理解的,我们可以定义一个find函数,find(x)表示点x所在的集合的根节点,那么我们只要询问点x的父亲点是否为他自己,如不是再询问x的父亲…一直找到根节点为止,那么就有这样一段代码: code: 1 int find(int o) 2 { 3 if(o==fa[o])return o;//如果点o的父亲点是他自己

团伙

怎甘沉沦 提交于 2019-12-03 02:48:16
传送门 解题思路 加权并查集: 什么是加权并查集? 就是记录着每个节点到它的父亲的信息(权值等)。 难点: 在路径压缩和合并节点时把本节点到父亲的权值转化为到根节点的权值 怎么转化呢? 每道题都不一样QAQ 看一看这道题我们用r[x]=0表示是x和f[x]是同种生物,等于1表示x吃f[x],等于2表示x是f[x]的食物。 从x点到f[x]的权值更新为i点到祖宗的权值的方法: 由于路径压缩是递归实现,所以其实返回f[x]=find(f[x])时,f[f[x]]就是祖宗。 所以其实就是这样一张图: 然后放到这个题上,不难发现r[x]=(r[x]+r[f[x]])%3。 大胆猜想,无需证明!! 然后就是合并: 先放图吧!F1是A的祖宗,F2是B的祖宗。 把A和B合并起来(A的祖宗的父亲定为B的祖宗)本质上就是求r[f1]。 而x是知道了的——当A和B是同类时,x就是0,当A吃B时,x就是1。 所以很显然,r[f1]=(r[b]+x-r[a]+3)%3。(因为有可能出现负数,所以+3后再%3) 大胆猜想,无需证明!! 种类并查集: 对于种类并查集不了解的可以下看一下这道较为简单的题—— 团伙 。 了解了种类并查集后,再来看看这道题:用三个并查集分别维护同类,食物,天敌(把f数组开三倍大小——1~n,n+1~2*n,n*2+1~3*n)。 对于每一次数据—— 当1时

[算法总结]并查集

為{幸葍}努か 提交于 2019-12-03 02:35:49
目录 一、关于并查集 1. 定义 2. 基本操作 3. 具体实现 二、代码实现 三、一些例题 例1: P1551 亲戚 例2: P1536 村村通 例3: P1396 营救 例4: P1621 集合 例5: P4185 [USACO18JAN]MooTube 例6: P1197 [JSOI2008]星球大战 例7: bzoj2054疯狂的馒头 例8: P2294 [HNOI2005]狡猾的商人 例9: P1892 [BOI2003]团伙 一、关于并查集 1. 定义 并查集(Disjoint-Set)是一种可以动态维护若干个不重叠的集合,并支持 合并 与 查询 两种操作的一种数据结构。 2. 基本操作 1. 合并(Union/Merge) 1 : 合并两个集合。 2. 查询(Find/Get): 查询元素所属集合。 实际操作时,我们会使用一个点来代表整个集合,即一个元素的根结点(可以理解为父亲)。 3. 具体实现 我们建立一个数组 fa[ ] 或 pre[ ] 表示一个并查集, fa[i] 表示 i 的父节点。 初始化: 每一个点都是一个集合,因此自己的父节点就是自己 fa[i]=i 查询: 每一个节点不断寻找自己的父节点,若此时自己的父节点就是自己,那么该点为集合的根结点,返回该点。 修改: 合并两个集合只需要合并两个集合的根结点,即 fa[RootA]=RootB ,其中