并查集

并查集(算法描述)

北慕城南 提交于 2020-02-14 03:32:19
例题: C. News Distribution(第一次打) time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output In some social network, there are n n users communicating with each other in m m groups of friends. Let's analyze the process of distributing some news between users. Initially, some user x x receives the news from some source. Then he or she sends the news to his or her friends (two users are friends if there is at least one group such that both of them belong to this group). Friends continue sending the news to their friends, and so on. The process ends

学习笔记 | 并查集

故事扮演 提交于 2020-02-13 01:58:49
并查集 01 并查集的定义 并查集 是一种维护集合的数据结构。并查集是用一个数组实现的。 1⃣️ 合并 Union :合并两个集合。 2⃣️ 查找 Find :判断两个元素是否在一个集合。 同一个集合,只存在一个根结点。 02 并查集的基本操作 1⃣️ 初始化 2⃣️ 查找 3⃣️ 合并 把一个集合的根结点的父亲指向另一个集合的根结点。 并查集产生的每一个集合都是一棵树。 03 路经压缩 应用: 判断无向图中是否有环。 来源: CSDN 作者: 大虎牙 链接: https://blog.csdn.net/qq_34170700/article/details/104281159

并查集

六眼飞鱼酱① 提交于 2020-02-12 12:17:28
并查集是一种用来管理元素分组情况的数据结构,可以高效的执行下面的操作: 1.查寻(find):查询元素a和b是否属于同一分组; 2.合并(union):将两个不同的分组合并为一个分组。 注意并查集虽然可以进行合并操作,但是却无法进行分割操作。 并查集的结构 并查集使用树形结构实现,整个并查集由一颗或多棵树构成,每棵树代表一个分组。在并查集中,哪个节点是哪个节点的父亲以及树的形状等信息并不重要,整体形成一个树状结构才是关键。但是,在实际应用中,我们通常使用每个分组的根节点代表分组编号。 初始化 并查集初始状态是每个元素都属于自身的子集,即每个子集仅有一个元素。 int fa[MAXN]; // 记录每个元素的父亲,初始化就是将每个元素的父亲设置为自身 void makeSet(int size) { for (int i = 1; i <= size; i++) fa[i] = i; } 查询分组 查找就是查看每个元素属于哪个分组,即通过该节点不断的查看自己的父亲,直到找到根节点。 int find(int x) { if (fa[x] == x) return x; return find(fa[x]); } 合并 合并就是将两个分组合并为一个分组,首先找到两个分组的根,然后从一个分组的根向另一个分组的根两边,这样,两棵树就成为了一颗树,也就把两个组合并为一个组了。 void

Bipartite Checking[CF813F][线段树分治][带权并查集]

时间秒杀一切 提交于 2020-02-12 02:20:48
文章目录 题目 思路 代码 题目 Luogu 2 ≤ n , q ≤ 1 0 5 2\le n,q\le 10^5 2 ≤ n , q ≤ 1 0 5 思路 通过带权并查集判断二分图真是妙(以前没见过) 首先我们能找到每条边的出现时间 [ l i , r i ] [l_i,r_i] [ l i ​ , r i ​ ] ,那么线段树分治后 发现是一个区间修改,单点查询的样子,修改标记永久化即可 然后就只剩下如何处理加边和删边的问题了 然后发现好像网上都把判断二分图当作众所周知… 我们使用带权并查集来解决这个问题,具体而言定义 f a [ u ] = u fa[u]=u f a [ u ] = u 的节点颜色为 0 0 0 ,然后每个点上有一个标记 c u c_u c u ​ 表示和 f a [ u ] fa[u] f a [ u ] 的颜色异同关系,显然一个点的颜色就是它到根的 c u c_u c u ​ 异或和 可以用线段树懒标记类比 一次 ( u , v ) (u,v) ( u , v ) 的加边操作如何实现? 如果 ( u , v ) (u,v) ( u , v ) 不连通,我们首先得到 u , v u,v u , v 各自颜色,如果不同那么并查集合并表示连通性,颜色相同将其中一个并查集顶端颜色变换连接即可 如果 ( u , v ) (u,v) ( u , v ) 连通

hdu4424 并查集+贪心+思维

限于喜欢 提交于 2020-02-11 18:37:05
#include<bits/stdc++.h> #define MAXN 200005 using namespace std; long long n,tot; long long f[MAXN],cnt[MAXN],ans[MAXN]; struct node{ long long from,to,cost,next,tp; }e[MAXN<<1]; void init(){ tot=0; memset(ans,0,sizeof(ans)); for(int i=1;i<=n;i++)f[i]=i,cnt[i]=1; } void add(long long x,long long y,long long z){ tot++; e[tot].from=x; e[tot].to=y; e[tot].cost=z; } long long found(long long x){ if(f[x]==x)return x; int fa=found(f[x]); f[x]=fa; return fa; } bool cmp(node x,node y){ return x.cost>y.cost; } int main(){ while(scanf("%lld",&n)==1){ init(); for(int i=1;i<n;i++){ long long x,y,z; scanf(

并查集---体会以及模板&&How Many Tables - HDU 1213

北战南征 提交于 2020-02-10 21:48:24
定义&&概念: 啥是并查集,就是将所有有相关性的元素放在一个集合里面,整体形成一个树型结构,它支持合并操作,但却不支持删除操作 实现步骤: (1)初始化,将所有节点的父亲节点都设置为 自己 ,例如pre[1]=1 (2)合并,将一个元素或者一集合(两者间有联系)合并到另外一个集合(元素)里面,谁是谁的父亲节点 不需要 过多在意,视题意而定。 (3)查找,在合并时需要运用到查找操作,即查找该元素的父节点,尽量使用 路径压缩 ,可以使并查集更加高效,一旦使用了路径压缩,查询时就会将该查询元素到父亲的边改为直接连向根。 这道模板题方便理解: 并查集模板题 How Many Tables - HDU 1213 - Virtual Judge 题意: 今天是Ignatius的生日,他邀请了许多朋友。现在是吃晚饭的时间,Ignatius想知道他至少需要准备多少桌。 必须注意的是,并非所有的朋友都相互认识对方,有的人不愿意和陌生人坐在一桌。 针对此问题的一个重要的规则是,如果我告诉你A知道B,B知道C,这意味着,A和C认识对方,这样他们就可以留在一个桌子。但是如果我告诉你,A知道B,B知道C,D知道E,那么ABC可以坐在一起,DE就得另外再坐一桌了。你的任务是请根据输入的朋友之间的关系,帮助Ignatius 求出需要安排多少桌。 input: 2 5 3 1 2 2 3 4 5 5 1 2 5

P1111 修复公路(并查集)

生来就可爱ヽ(ⅴ<●) 提交于 2020-02-08 23:51:59
题意: 给你n个点,m条无向边,每条边建好都有一个时间,问什么时候各个点能互相可达 思路: 将每条边按时间排序,每次加入一条边,看边连接的两点是否在一个连通块内,不在的话合并连通块,看是否总连通块个数为1即可 #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; const int maxn1=1e5+10; const int maxn2=1e3+10; int fa[maxn2],siz[maxn2],n,m; struct node{ int u,v,t; }edge[maxn1]; int cmp(node a,node b){return a.t<b.t;} int find(int x){return fa[x]==x?x:(fa[x]=find(fa[x]));} int main() { scanf("%d%d",&n,&m); for(int i=0;i<m;i++) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].t); sort(edge,edge+m,cmp); for(int i=1;i<=n;i++) fa[i]=i; memset(siz,0,sizeof(siz));

并查集(Java)

人走茶凉 提交于 2020-02-08 18:06:08
并查集 并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林(多棵树)来表示。 UF.java(并查集接口) //并查集接口 public interface UF { int getSize ( ) ; //返回并查集中树的个数,即集合的个数 boolean isConnected ( int p , int q ) ; //查询元素p与元素q是否连接 void unionElements ( int p , int q ) ; //将元素q与元素p进行合并 } UnionFind.java(并查集) //并查集 public class UnionFind implements UF { private int [ ] parent ; // 基础数组形成多棵树结构 // private int[] sz;// sz[i]表示以i为根的集合节点个数 private int [ ] rank ; // rank[i]表示以i为根的集合所表示的树的层数(h) public UnionFind ( int size ) { // TODO

带权并查集——食物链

狂风中的少年 提交于 2020-02-08 16:03:42
并查集是常见而且好用的一种数据结构。原因在于代码简练而且方便维护各种额外信息。带权并查集就是并查集的一种应用方式。原理其实就是普通并查集额外维护了一个结点的权数组。 例题: 本题的关系有三层 -> a -> b -> c -> ,但不同的是本题的关系是有向的,也就是说a和b如果是敌对关系,那么b和a就不是敌对关系。 关系传递的本质实际上是向量的运算。 还是设 d[x] 表示 x 与 fa[x] 的关系,0 代表是同类,1 代表是x吃fa[x], 根据关系图自然2就代表x被fa[x]吃。 #include<iostream> using namespace std; const int N = 500010; int p[N]; int d[N];//带权并查集的权值0 1 2 三个值分别表示是同类,吃根节点,和被根节点吃; int n,m,k,a,b; int find(int x) { if(p[x] == x) return x; int r = find(p[x]); d[x] += d[p[x]]; return p[x] = r; } int main(){ cin>>n>>m; for(int i = 0 ; i <= n ; i++){ p[i] = i; } int res = 0; for(int i = 0 ; i < m ; i ++){ cin>>k>>a>

ACWing 240(并查集 扩展域)

断了今生、忘了曾经 提交于 2020-02-06 12:53:20
动物王国中有三类动物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句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。 1) 当前的话与前面的某些真的话冲突,就是假话; 2) 当前的话中X或Y比N大,就是假话; 3) 当前的话表示X吃X,就是假话。 你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。 Input 第一行是两个整数N和K,以一个空格分隔。 以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 若D=1,则表示X和Y是同类。 若D=2,则表示X吃Y。 Output 只有一个整数,表示假话的数目。 Sample Input 100 7 1 101 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5 Sample Output 3 解题思路:我们可以使用带权并查集来做