日常膜拜dalao:财神万岁!!!!!!!!!!!!!!!!!!!!
emm因为刚刚写了一篇题解想起来要写并查集的了,然而明天分班考试我丝毫不慌稳如泰山甚至还贼想写博客。。。
不相交数据结构。维护一个森林,使得每棵树之间不相交,并能够统计出有多少个独立的树 。染色方法,不断地合并,顺便路径压缩,把同一个树的高度尽量降低来进行时间优化 。
看不懂是不是?没关系我们通俗一点。
假设我们已知一堆关系,A和B是亲戚,B和C是亲戚,那么A和C也是亲戚。
给你这些关系,让你梳理好他们之间谁谁之间都是亲戚。
找祖先函数:找到x 的最早的祖先,然后把跟x 有关系的都连接到x 的祖先上,这样查询会方便很多也快捷很多,不然一层层找下来很烦的qwq
初始化:很重要!每个人最初开始的祖先都是他本身。
emm剩下的代码里面很清楚,看代码吧
include<iostream>//并查集
#define maxn 105
#define maxm 105
using namespace std;
int m,n;// n个点,m 条边
int f[maxn]; //祖先
int h[maxn]; //树高
void chushihua()//初始化,一定要有!
{
for(int i=1;i<=n;i++){
h[i]=1;//树高
f[i]=i;//祖先最开始是它本身
}//初始化每一个点
return;
}
int get(int x)//找祖先的函数
{
if(f[x]==x) return x;//如果祖先是他自己时返回自己
else{
f[x]=get(f[x]);//找到他的最终祖先
return f[x];//顺便路径压缩,一层一层返回上去它的祖先
}
}
void merge(int a,int b)//将a和b合并到一棵树上面
{
int t1=get(a),t2=get(b);//分别找a,b的最终祖先
if(t1==t2) return;//已经在同一棵树中
if(h[t1]<h[t2]) swap(t1,t2);//靠左原则,左边比右边的树要高
if(t1!=t2){
f[t2]=t1;//左边的变成右边的祖先
h[t1]=max(h[t1],h[t2]+1);//合并树高,原树高与合并来的比较并进行更新
}
return;
}
int main()
{
cin>>n>>m;
chushihua();
for(int i=1;i<=m;i++)
{
int a;int b;
cin>>a>>b;
merge(a,b);//合并a,b所在的树
}
。。。。。。//其他操作
return 0;
}
我们用f[i]表示i的祖先,当每次需要查找i和j之间的关系时,只需要查找 f[i]和f[j]之间的关系,h数组是树高,当合并两棵树时,我们优先把低的树合并到高的树上面,对时间复杂度进一步优化。
emm其实我讲的一点也不仔细,,如果实在看不明白这里有一片详细的多的大佬的博客
友情链接:https://blog.csdn.net/Martisum/article/details/99721621
本文如有不周到处欢迎评论,
感谢各位神犇对本蒟蒻的支持!qwq