什么是并查集
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题,可以用来检查一个图中是否存在一个环。
算法原理
代码模板
#include<iostream>
using namespace std;
int parent[1010];
int n,m;
void init(int n)//初始化
{
for(int i=1;i<=n;i++)
{
parent[i]=-1;
}
}
int find_root(int x,int parent[])//查找根节点
{
int x_root=x;
while(parent[x_root]!=-1)//只有根节点才是-1
{
x_root=parent[x_root];
}
return x_root;
}
int unite(int x,int y,int parent[])//链接,返回0说明不用连接(即在一棵树上)
//返回1表示可以连接
{
int x_root=find_root(x,parent);
int y_root=find_root(y,parent);
if(x_root==y_root)
{
return 0;
}
else
{
parent[x_root]=y_root;
return 1;
}
}
并查集的优化
优化代码模板
#include<iostream>
using namespace std;
int parent[1010];
int n,m;
void init(int n,int rank[])
{
for(int i=1;i<=n;i++)
{
parent[i]=-1;
rank[i]=0;
}
}
int find_root(int x,int parent[])
{
int x_root=x;
while(parent[x_root]!=-1)
{
x_root=parent[x_root];
}
return x_root;
}
int unite(int x,int y,int parent[],int rank[])
{
int x_root=find_root(x,parent);
int y_root=find_root(y,parent);
if(x_root==y_root)
{
return 0;
}
else
{
//parent[x_root]=y_root;
if(rank[x_root]>rank[y_rank])
parent[y_root]=x_root;
else if(rank[x_root]<rank[y_root])
parent[x_root]=y_root;
else//两棵树高度相等任选一棵连接到另一棵上,同时另一棵的高度加一
{
parent[x_root]=y_root;
rank[y_root]++;
}
return 1;
}
}
题目练习
代码:
#include<iostream>
using namespace std;
int parent[1010];
int n,m;
void init(int n)
{
for(int i=1;i<=n;i++)
{
parent[i]=-1;
}
}
int find_root(int x,int parent[])
{
int x_root=x;
while(parent[x_root]!=-1)
{
x_root=parent[x_root];
}
return x_root;
}
int unite(int x,int y,int parent[])
{
int x_root=find_root(x,parent);
int y_root=find_root(y,parent);
if(x_root==y_root)
{
return 0;
}
else
{
parent[x_root]=y_root;
return 1;
}
}
int main ( )
{
while(cin>>n&&n)
{
cin>>m;
// int parent[n+1];
init(n);
int x,y;
for(int i=1;i<=m;i++)
{
cin>>x>>y;
unite(x,y,parent);
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(parent[i]==-1)//看形成了几棵树,最后将它们连接就可
{
ans++;
}
}
cout<<ans-1<<endl;
}
return 0;
}