借鉴:https://blog.csdn.net/zjy_code/article/details/80634149
模板题(洛谷):https://www.luogu.org/problemnew/show/P3367
基础:
两种基本操作:
1.get(查询根节点)
2.merge(将两个集合合并)
如何定义(初始化)?
int father[MAXN]; void inti() { for(int i=1;i<=n;i++) { father[i]=i; } }
先定义一个数组father[],father[i]代表i的父亲节点;如果,father[i]=i,那么i就是根节点。
get():
int get(int x){ if(father[x]==x) return x; return father[x]=get(father[x]); }
递归求根节点。
merge():
int merge(int x,int y){ father[get(x)] = get(y); }
合并,让y作为x儿子;实际上就是让y的根成为x的根的儿子节点。
重点!!!
并查集模板:
#include<bits/stdc++.h> using namespace std; int n,m; int z; int father[200100]; void dingyi()//初始化 { for(int i=1;i<=n;i++) { father[i]=i; } } int get(int x)//寻找根节点 { if(father[x]==x) return x; return father[x]=get(father[x]); } int merge(int x,int y)//合并 { if(get(x) != get(y)) father[get(x)]=get(y); } int main() { int a,b; cin>>n>>m;//n表示有n个元素;m表示以下有m个操作 dingyi(); for(int i=0;i<m;i++) { cin>>z>>a>>b;//如果z==1,则合并a,b两个元素;若z==2,则判断a和b是否在同一个集合里面;是,输出"Y",不是,输出"N" if(z==1) { merge(a,b); } else if(z==2) { if(get(a) != get(b)) cout<<"N"<<endl; else cout<<"Y"<<endl; } } return 0; }
这是以洛谷的P3367题为题目做的。
看完模板之后,有些童鞋就要问了:“这模板不就是把那些基础的东西拼在一起吗?”
额........我只能说————You are right!
所以,传说中的并查集貌似并没有多难嘛(我信你个鬼)
这只是个模板而已,并不代表并查集的真正实力,刚刚你们刷的,其实只是小怪,正真的BOSS还没……
警告!!!BOSS来袭!!!
……到呢。额,说曹操曹操到,让我们拿起我们的神级武器:键盘、鼠标,发动终极技能:C++ 吧!
BOSS(均来自“洛谷”星):
①难度:普及- ;代号:P1551; 名字:亲戚; 击败可获得成就:初窥门道
②难度:普及/提高-; 代号:P2078; 名字:朋友 ; 击败可获得成就:熟能生巧
③难度:普及+/提高; 代号:P2412; 名字:查单词; 击败可获得成就:能工 oi 巧匠 er
④难度:提高+/省选-; 代号:CF741B; 名字:Arpa's weak amphitheater and Mehrdad's valuable Hoses(呀!还是个进口的BOSS);击败可获得成就:大佬
⑤(需要通过P3402方能挑战此BOSS)难度:省选/NOI-; 代号:CF292D; 名字:Connected Components(考验你的英文水平的时候到了QAQ!);击败可获得成就:你已经接近神啦!
⑥难度:NOI/NOI+/CTSC; 代号:P3300; 名字:城市规划; 击败可获得成就:还有谁!!!
当你击败这里所有的BOSS的时候
你应该站在清北的校门口,手里握着录取通知书……