以前学最小生成树的时候,就一直听并查集的大名,就是一直没去看,所以最小生成树也没搞明白。
等接触到并查集之后才知道,用来是这一类问题啊。(纯属吐槽)
并查集是用来判断图的连通性的一种算法。
并查集是一种已知叶寻找根的一种算法,大概分为两个部分,前面一个我叫他寻根,后一个我叫他并集。
初始化数组:
for(int i=0;i<n;i++)//n表示输入的结点的个数
pho[i]=i;//将每一个结点的前导点设置为自己
寻根函数:
int find(int r)
{
while(r != pho[r])
r = pho[r];
return r;
}
并集函数:
void join(int x,int y)
{
int fx = find(x),fy = find(y);
if(fx != fy) pho[fx] = fy;
}
但是如果采取这种寻根操作的话,很显然,树的层数会很大。
很显然树的层数越大,对于该树的遍历就会越麻烦,所以我们可以采取路径压缩。
int better_find(int r)
{
int x = r;
while(r != pho[r])
r = pho[r];
int i = x,j;
while(i != r){
j = pho[i];
pho[i] = r;
i = j;
}
return r;
}
很显然,通过压缩之后,我们的树就只有两层,对于后面的计算是相当方便的。
上一波完整代码。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double dl;
const int N = 1e6 + 7;
int pho[N];
int relation[N][2];
int find(int r)
{
int x = r;
while(r != pho[r])
r = pho[r];
int i = x,j;
while(i != r){
j = pho[i];
pho[i] = r;
i = j;
}
return r;
}
void join(int x,int y)
{
int fx = find(x),fy = find(y);
if(fx != fy) pho[fx] = fy;
}
int main()
{
int n,m,p,k;
cin >> n >> m;
for(int i = 1;i <= n;++i)
pho[i] = i;
for(int i = 1;i <= m;++i)
cin >> relation[i][0] >> relation[i][1];
for(int i = 1;i <= m;++i)
join(relation[i][0],relation[i][1]);
int t;
cin >> t;
while(t--){
cin >> p >> k;
int a = find(p),b = find(k);
a == b ? cout << "Yes" <<endl : cout << "No" << endl;
}
return 0;
}
这个代码的作用是已知10个节点,给出m组关系,求给t组数据是否连通