……我觉得我需要写一下并查集……毕竟我这么菜……不写篇博客过几天我都不知道自己学过 找爸爸 并查集了
但我这么菜,我也写不出太多东西……那就让这俩一起吧QwQ 反正kruscal也要用并查集的QwQ
并查集
并查集,俗称找爸爸(雾),就是多个集合之间的查询&合并,具体操作包括:查询某两点是否在同一集合,合并某两点所在集合,以及一些鬼畜的操作
先贴代码,再说思想
int find(int x)
{
if (f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
上面的是并查集最最最核心的操作:找爸爸
其实原理非常的简单:如果x不是自己的爸爸,那么x一定不是根节点,于是我们再去找x的爸爸的爸爸,直到x的爸爸的爸爸的爸爸的……p终于是自己的爸爸了,于是x和他的爸爸们都找到了他们的爸爸,也都直接把他们的爸爸变成了p,这其实也就是路径压缩
找到了爸爸,接下来就是查询操作
原理更简单了,(代码我都不想放),分别查询两个节点的爸爸,看看这两个点的爸爸是不是一个爸爸
最后就是合并操作了
更简单了,把一个点的爸爸变成另一个点的爸爸的儿子
放整体代码(这是洛谷模板题)洛谷3367的传送门QwQ
#include<bits/stdc++.h>
using namespace std;
int f[10010];
int fa(int x)
{
if (f[x]==x)
return x;
return f[x]=fa(f[x]);
}
int main()
{
int n,m;
cin>>n>>m;
for (int i=1;i<=n;i++)
f[i]=i;
for (int i=1;i<=m;i++)
{
int z,a,b;
cin>>z>>a>>b;
if (z==1)
f[fa(a)]=fa(b);
if (z==2)
if (fa(a)==fa(b))
cout<<"Y"<<endl;
else
cout<<"N"<<endl;
}
return 0;
}
咳咳咳接下来是kruscal
Kruscal
一个简陋的、没什么用的、目录
- 算法思想
- 直接上代码
算法思想
从小到大遍历每条边,如果这条边的两个端点不在一个集合里,就合并他们,直到所有点都被连起来
代码实现
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<algorithm>
#include<queue>
#include<cstdlib>
using namespace std;
int jishuqi,f1,f2,f[10100];
struct edge
{
int a,b,val;
}e[10010];
int find(int x)
{
if (f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
bool cmp(edge a,edge b)
{
return a.val<b.val;
}
int main()
{
int n,m;
cin>>n>>m;
for (int i=1;i<=n;i++)
f[i]=i;
for (int i=1;i<=m;i++)
cin>>e[i].a>>e[i].b>>e[i].val;
sort(e+1,e+m+1,cmp);
for (int i=1;i<=m;i++)
{
f1=find(e[i].a);
f2=find(e[i].b);
if (f1==f2)
continue;
else
{
f[f1]=f[f2];
jishuqi=jishuqi+e[i].val;
}
}
cout<<jishuqi;
return 0;
}
【完结撒花✿✿ヽ(°▽°)ノ✿】【这次好草率的说】