并查集

深谈并查集

ぃ、小莉子 提交于 2019-12-03 00:06:33
我们理解并查集这个数据结构的时候不要过于 死板 , 我们要知道 并查集是用来维护关系的,而不是 单纯一味 去归,并,归,并,归,并 以前我就是一味的只知道 归,并,归,并 要深刻理解只有通过做题来打磨 https://www.luogu.org/problem/P2502 吐槽: 这道题把我坑惨了 花了半晚上去做,最后发现我的思路是错的 应该开始看数据范围的时候就该察觉了 说到底还是对并查集理解不够深刻 分析: 先对边进行排序 再n^2^枚举,跑生成树跟新答案 开始枚举的i一定是minn 最后枚举到find(s)==find(t)时j就maxx 不断跟新答案 直到再也无法S与T连通为止 code: #include <cstdio> #include <algorithm> #define maxn 600 #define maxm 5010 using namespace std; int n,m,s,t; int father[maxn]; int ans1,ans2; struct rec { int a,b,len; } c[maxm]; bool cmp(rec a,rec b) {return (a.len<b.len);} int getfather(int x) { if (father[x]==x) return x; return father[x]

树 dfs暴力判环 题意转化

匿名 (未验证) 提交于 2019-12-03 00:06:01
以后还是要多做题啊 这一道题我把题目想的太简单了 用并查集做了一波 但是忘了一种情况 就是同一个树上可能会有环 这就不太对了 而且还不要忘了 一棵树的根节点是一个自环 也就是说这一题的答案就是 环的数量-1(有一棵树的根节点不用改) 就是dfs一波就行了 下一次读清楚题! 来源:博客园 作者: DreamingBligo_Tido 链接:https://www.cnblogs.com/Tidoblogs/p/11523993.html

[笔记] 带权并查集与种类并查集

匿名 (未验证) 提交于 2019-12-03 00:03:02
作为一个要考试的人,还不会并查集,简直了。。。 先上一道题: P2024 [NOI2001]食物链 相信大家都会吧QwQ #include < bits / stdc ++. h > #define R register int using namespace std ; namespace Luitaryi { inline int g () { R x = 0 , f = 1 ; register char ch ; while (! isdigit ( ch = getchar ())) f = ch == '-' ?- 1 : f ; do x = x * 10 +( ch ^ 48 ); while ( isdigit ( ch = getchar ())); return x * f ; } const int N = 50010 ; int n , m , fa [ N ], d [ N ], ans ; inline int getf ( int x ) { if ( x == fa [ x ]) return x ; R f = getf ( fa [ x ]); d [ x ]=( d [ x ]+ d [ fa [ x ]])% 3 ; return fa [ x ]= f ; } inline void merge ( int u , int v , int

[NOIP2010]关押罪犯(并查集)

匿名 (未验证) 提交于 2019-12-02 23:57:01
题目描述 S 城现有两座监狱,一共关押着 N 名罪犯,编号分别为 。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为 c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为 c 的冲突事件。 每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。 在详细考察了 N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。 那么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少? 输入输出样例 输入 #1 复制 4 6 1 4 2534 2 3 3512 1 2 28351 1 3 6618 2 4 1805 3 4 12884 输出 #1 复制 3512 说明/提示 【输入输出样例说明】罪犯之间的怨气值如下面左图所示,右图所示为罪犯的分配方法,市长看到的冲突事件影响力是 3512

[BOI2003]团伙(并查集)

匿名 (未验证) 提交于 2019-12-02 23:56:01
题目描述 1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。而且有一点是肯定的,就是: 我朋友的朋友是我的朋友; 我敌人的敌人也是我的朋友。 两个强盗是同一团伙的条件是当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙。 输入格式 输入文件gangs.in的第一行是一个整数N(2<=N<=1000),表示强盗的个数(从1编号到N)。 第二行M(1<=M<=5000),表示关于强盗的信息条数。 以下M行,每行可能是F p q或是E p q(1<=p q<=N),F表示p和q是朋友,E表示p和q是敌人。输入数据保证不会产生信息的矛盾。 输出格式 输出文件gangs.out只有一行,表示最大可能的团伙数。 输入输出样例 输入 #1 复制 6 4 E 1 4 F 3 5 F 4 6 E 1 2 输出 #1 复制 3 在题解学习了反集qwq #include <cstdio> #include <iostream> using namespace std ; int n , m , s , x , y , fa [ 2500 ]; char t ; int find ( int x ) { if ( fa [ x ] != x ) fa [ x ] = find ( fa [ x ]); return fa [ x ]; }

带权并查集模板

匿名 (未验证) 提交于 2019-12-02 23:51:01
#include<cstdio> #include<iostream> using namespace std; int f[30005],d[30005],s[30005]; int find(int x) { if(f[x]==x)return x; int tmp=find(f[x]); d[x]+=d[f[x]]; return f[x]=tmp; } void move(int x,int y) { int sx=find(x); int sy=find(y); if(sx==sy)return ; f[sx]=sy; d[sx]=s[sy]; s[sy]+=s[sx]; } void search(int x) { find(x); printf("%d\n",d[x]); } int main() { int q; scanf("%d",&q); for(int i=1;i<=30000;i++) { f[i]=i; d[i]=0; s[i]=1; } while(q--) { char pd; cin>>pd; if(pd=='M') { int x,y; scanf("%d%d",&x,&y); move(x,y); } else if(pd=='C') { int x; scanf("%d",&x); search(x); } } return 0; }

[kuangbin带你飞]专题五 并查集 D - How Many Answers Are Wrong(带权并查集)

匿名 (未验证) 提交于 2019-12-02 23:51:01
D - How Many Answers Are Wrong 题目链接: https://vjudge.net/contest/66964#problem/D 题目: TT and FF are ... friends. Uh... very very good friends -________-b FF is a bad boy, he is always wooing TT to play the following game with him. This is a very humdrum game. To begin with, TT should write down a sequence of integers-_-!!(bored). Then, FF can choose a continuous subsequence from it(for example the subsequence from the third to the fifth integer inclusively). After that, FF will ask TT what the sum of the subsequence he chose is. The next, TT will answer FF's question. Then, FF can redo this

洛谷P1525 关押罪犯(并查集、二分图判定)

匿名 (未验证) 提交于 2019-12-02 23:49:02
https://www.luogu.org/problemnew/show/P1525 题目描述 S城现有两座监狱,一共关押着 N名罪犯,编号分别为 1 N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为 c c的冲突事件。 每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。 在详细考察了 N名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。 那么,应如何分配罪犯,才能使Z市长看到的那个冲突事件的影响力最小?这个最小值是多少? 输入输出格式 输入格式: 每行中两个数之间用一个空格隔开。第一行为两个正整数 N , M,分别表示罪犯的数目以及存在仇恨的罪犯对数。接下来的 M行每行为三个正整数 a j , b j , c j ,表示 a j b j 号罪犯之间存在仇恨,其怨气值为 c j 。数据保证 1 < a j

并查集+路径压缩

匿名 (未验证) 提交于 2019-12-02 23:47:01
感觉这篇文章总结的挺好的,转自 https://www.cnblogs.com/lisijie/p/7694791.html 初始化: void init(int n) { for (int i=0;i<n;i++) { parent[i]=i; rank[i]=0; } } 查询根节点: int Find(int x) { if (parent[x]==x) return x; else return parent[x]=Find(parent[x]); } 合并集合: void Unite(int w,int v) { int x=Find(w); int y=Find(v); if(x==y) return ; if (rank[x]<rank[y]) parent[x]=y; else{ parent[y]=x; if (rank[x]==rank[y]) rank[x]++; parent[x]=y; } 路径压缩: ①递归: int Find(int x) //查找x元素所在的集合,回溯时压缩路径 { if (x != parent[x]) { parent[x] = Find(parent[x]); //回溯时的压缩路径 } //从x结点搜索到祖先结点所经过的结点都指向该祖先结点 return parent[x]; } ②非递归: int Find(int x) {

并查集(入门)

匿名 (未验证) 提交于 2019-12-02 23:45:01
首先先看一道很简单的并查集的题目: https://vjudge.net/contest/297398#problem/A 这道题就是让你判断两两城镇之间是否联通  如果不联通就要修建一条道路 就我的理解来说,如果 单独使用并查集 就是为了合并 有相同根结点(或者理解成有相同的性质)的这样的数据 这里我们引入一个我在网上看到的一个关于并查集的一个很有意思的故事: 并查集由一个整数型的数组和两个函数构成。 数组pre[]记录了每个点的前导点是什么   函数find是查找   函数join是合并 。 话说江湖上散落着各式各样的大侠,有上千个之多。他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的,就免不了要打一架。但大侠们有一个优点就是讲义气,绝对不打自己的朋友。而且他们信奉“朋友的朋友就是我的朋友”,只要是能通过朋友关系串联起来的,不管拐了多少个弯,都认为是自己人。这样一来,江湖上就形成了一个一个的群落,通过两两之间的朋友关系串联起来。而不在同一个群落的人,无论如何都无法通过朋友关系连起来,于是就可以放心往死了打。但是两个原本互不相识的人,如何判断是否属于一个朋友圈呢? 我们可以在每个朋友圈内推举出一个比较有名望的人,作为该圈子的代表人物,这样,每个圈子就可以这样命名“齐达内朋友之队”“罗纳尔多朋友之队”……两人只要互相对一下自己的队长是不是同一个人