并查集

poj2524(简单并查集)

大兔子大兔子 提交于 2019-12-18 01:53:53
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> using namespace std; int n,m; int bin[50001]; int findx(int x) { int r=x; while(r!=bin[r]) r=bin[r]; int j=x,k; while(j!=r) { k=bin[j]; bin[j]=r; j=k; } return r; } void merge(int x,int y) { int fx=findx(x); int fy=findx(y); if(fx!=fy) bin[fy]=fx; } int main() { int x,y,k=0; while(scanf("%d%d",&n,&m)!=EOF) { k++; if(n==0&&m==0) break; for(int i=0;i<=n;i++) bin[i]=i; while(m--) { scanf("%d%d",&x,&y); merge(x,y); } int sum=0; for(int i=1;i<=n;i++) if(bin[i]==i) sum++; printf("Case %d: %d\n",k,sum); } return 0; } 来源:

【拓扑结构+并查集】HDU - 1811 Rank of Tetris

北城余情 提交于 2019-12-16 08:49:55
题目 自从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),分别表示要排名的人数以及得到的关系数。

F-找朋友(裸并查集)

久未见 提交于 2019-12-15 19:01:29
题目链接: http://acm.csust.edu.cn/problem/3029 Description ——你要是愿意,我就永远存在 某人的朋友圈实在是过于庞大且复杂,要判断两个人是不是朋友,那还真不容易。 现给出某个朋友圈关系图,求任意给出的两个人是否是朋友。 规定:如果 x和 y y是朋友, y和 z是朋友,那么 x和 z也是朋友。 如果 x和 y 是朋友,那么 x 的朋友都是 y的朋友, y的朋友也都是 x 的朋友。 Input 第一行:三个整数 n , m , p,( n ≤ 5 0 0 0 0, m ≤ 5 0 0 0 0, p ≤ 5 0 0 0 0),分别表示有 n 个人, m个朋友关系,询问 p对朋友关系。 以下 m 行:每行两个数 M i ​ , M j ​ , 1 ≤ M i ​ , M j ​ ≤ n,表示 M i ​ 和 M j ​ 具有朋友关系。 接下来 p 行:每行两个数 P i ​ , P j ​ ,询问 P i ​ 和 P j ​ 是否具有朋友关系。 Output P 行,每行一个“Yes”或“No”(不包含引号)。表示第i个询问的答案为“具有”或“不具有”朋友关系。 Sample Input 1 6 5 3 1 2 1 5 3 4 5 2 1 3 1 4 2 3 5 6 Sample Output 1 Yes Yes No 裸的并查集

p1197 星球大战 (并查集)

我是研究僧i 提交于 2019-12-14 05:57:18
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系。 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。 但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。 现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通块的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。 输入格式 输入文件第一行包含两个整数,NNN (1<=N<=2M1 < = N < = 2M1<=N<=2M) 和 MMM (1<=M<=200,0001 < = M < = 200,0001<=M<=200,000),分别表示星球的数目和以太隧道的数目。星球用 000 ~ N−1N-1N−1 的整数编号。 接下来的 MMM 行,每行包括两个整数 XXX, YYY,其中( 0<=X<>Y0 < = X <> Y0<=X<>Y 表示星球 xxx 和星球 yyy 之间有 “以太” 隧道,可以直接通讯。 接下来的一行为一个整数 kkk

并查集--模版

一世执手 提交于 2019-12-12 21:10:49
题目描述 如题,现在有一个并查集,你需要完成合并和查询操作。 输入格式 第一行包含两个整数N、M,表示共有N个元素和M个操作。 接下来M行,每行包含三个整数Zi、Xi、Yi 当Zi=1时,将Xi与Yi所在的集合合并 当Zi=2时,输出Xi与Yi是否在同一集合内,是的话输出Y;否则话输出N 输出格式 如上,对于每一个Zi=2的操作,都有一行输出,每行包含一个大写字母,为Y或者N、 首先先定义数组:fa[]表示这一个点的父亲节点, 并查集一共包含三个部分: 1:初始化 先把所有的点的父亲节点都定义为他本身 1 void init(int n) 2 { 3 for (int i = 0 ;i<=n ;i++) 4 fa[i]=i; 5 } 2: 找根节点 如果此点的父亲节点是他本身,他就是父亲节点,如果不是就找他父亲节点的父亲节点        直到他的父亲节点是他本身 1 int find(int v) 2 { 3 if (v==fa[v]) 4 return v; 5 fa[v]=find(fa[v]); 6 return fa[v]; 7 } 3. 合并 把一个数的父亲节点指向另一个节点即把他们两个合并 void update(int u,int v) { int fu= find(u); int fv= find(v); fa[fu] =fv; } 完整代码: 1

并查集(带路径压缩)

天大地大妈咪最大 提交于 2019-12-11 15:03:41
并查集 用于快速查找集合中元素是否存在关系的数据结构,主要操作为: 查询 和 合并 并查集简述 常用的带有路径压缩版本的并查集模板: 带路径压缩的并查集在一般情况下的查询或者合并操作,其时间复杂度近似于O(1) #define MAXN 5000 int fa[MAXN+1]; void init(int n) { for(int i = 1; i <= n; i++) { fa[i] = i; //初始化 } } int find(int x) { if(fa[x]==x) return x; return fa[x] = find(fa[x]); //查询时进行路径压缩 } void merge(int x, int y) { fa[find(x)] = find(y); //合并 } 实战1:P1111 修复公路 思路:这题本质要求我们权为时间t的图的最小生成树,具体做法为:先将边按时间从小到大排序,然后依次判断取边,当构成生成树(下为ans==n-1)时即输出答案即可 赋AC代码: #include <stdio.h> #include <stdlib.h> #define MAXN 1000 int fa[MAXN+1]; typedef struct maye { int u, v, t; }ccc; void init(int n) { for(int i = 1;

算法专题 | 并查集

微笑、不失礼 提交于 2019-12-11 08:13:42
文章目录 并查集 1 模版题 AcWing 836.合并集合 AcWing 837.连通块中点的个数 AcWing 240.食物链 并查集 2 并查集模板 示例代码 LeetCode 547.FriendCircles LeetCode 200.NumberOfIslands LeetCode 684.Redundant Connection 并查集 1 一.并查集—合并+查找 并查集两个操作: 近乎0(1)时间复杂度内快速维护这两个操作 将两个集合合并 询问两个元素是在一个集合中 维护每个集合中元素的个数 见连通块中的点的个数 维护每个集合中元素与根节点的关系 见食物链 并查集的最本质是find函数,记这个就行了 二.基本原理 每个集合用一棵树来表示。树根的编号就是整棵树的编号。每个节点储存它的父节点,p[x]表示x的父节点 问题1. 如何判断树根:if(p[x] == x) 问题2. 如何求x的集合标号: while(p[x] != x) x = p[x]; 问题3. 如何合并两个集合: p[find(x)] = find(y) 优化-路径压缩 我找一次后,所有路径上的点指向跟节点 第一次求要三次,第二次就只需要一次 模版题 AcWing 836.合并集合 版本1 简练 # include <iostream> # include <cstdio> # include

并查集求最小环

社会主义新天地 提交于 2019-12-07 17:12:28
例题: 洛谷信息传递 求最小环是2015年NOIP的一道题,作为蒟蒻的我并不会这道题,看了题解之后做个笔记吧! 要求最小环我们得找出所有的环,找环的办法就是读入i的父亲之后,判断他俩是否现在已经连上了,如果已经连上了,那么就构成了一个环,此时就不需要再将他们两个连上了,不然就会死循环,这时估计就有人会问,不连上他们,那么如果有包含这一条边的环比你现在的环还小你不就错了么?(这就是这题的图的特殊了,因为对于每一个点只会有一个父亲,按照我们的遍历方式来看,所以此时 i 和 i的父亲 的父亲都已经知道了,那么就不可能再会有别的环经过这条边了),当然,如果此时父亲不同就把i并入 1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 #include<cstring> 5 #include<climits> 6 using namespace std; 7 int fa[200010]; 8 int res=INT_MAX; 9 int cnt=0; 10 int find(int x) 11 { 12 cnt++; 13 if(fa[x]==x) 14 return fa[x]; 15 else 16 return find(fa[x]); 17 } 18 int main() 19 { 20 int n; 21

洛谷P2661 信息传递——并查集

痞子三分冷 提交于 2019-12-07 01:13:49
给一手链接 https://www.luogu.com.cn/problem/P2661 这道题就是 并查集求最小环 TIPS:压缩路径的时候d[x]=d[fa【x】]+d[x],而不是d[x]=d[fa【x】]+1 因为路径是压缩过的 #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> using namespace std; const int M=1e6+7; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } int n,T,f[M],d[M]; int find(int x){ int F=f[x]; if(F==x) return F; f[x]=find(F); d[x]=d[F]+d[x]; return f[x]; } int ans=M; int main(){ n=read(); for(int i=1;i<=n;i++) f[i]=i,d[i]=0; for(int i

【BZOJ4668】冷战(并查集)

自闭症网瘾萝莉.ら 提交于 2019-12-06 21:59:34
Description 1946 年 3 月 5 日,英国前首相温斯顿·丘吉尔在美国富尔顿发表“铁幕演说”,正式拉开了冷战序幕。美国和苏联同为世界上的“超级大国”,为了争夺世界霸权,两国及其盟国展开了数十年的斗争。在这段时期,虽然分歧和冲突严重,但双方都尽力避免世界范围的大规模战争(第三次世界大战)爆发,其对抗通常通过局部代理战争、科技和军备竞赛、太空竞争、外交竞争等“冷”方式进行,即“相互遏制,不动武力”,因此称之为“冷战”。 Reddington 是美国的海军上将。由于战争局势十分紧张,因此他需要时刻关注着苏联的各个活动,避免使自己的国家陷入困境。苏联在全球拥有 N 个军工厂,但由于规划不当,一开始这些军工厂之间是不存在铁路的,为了使武器制造更快,苏联决定修建若干条道路使得某些军工厂联通。 Reddington 得到了苏联的修建日程表,并且他需要时刻关注着某两个军工厂是否联通,以及最早在修建哪条道路时会联通。具体而言,现在总共有M 个操作,操作分为两类: • 0 u v,这次操作苏联会修建一条连接 u 号军工厂及 v 号军工厂的铁路,注意铁路都是双向的; • 1 u v, Reddington 需要知道 u 号军工厂及 v 号军工厂最早在加入第几条条铁路后会联通,假如到这次操作都没有联通,则输出 0; 作为美国最强科学家, Reddington 需要你帮忙设计一个程序