DGZX1520 - 家族
并查集入门模板题。
【C++版本】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int pa[5001];
int rank[5001];
int n, m, p, a, b;
void init()
{
memset(pa,0,sizeof(int)*(n+1));
for (int i=1; i<=n; i++)// 各个子树高度初始化为 1
rank[i] = 1;
}
// 基本操作一:查找(递归版本)
int Find(int x)// 递归实现查找的时候,其实也实现了路径压缩
{
return pa[x]==0 ? x : pa[x] = Find(pa[x]);// 根的标志是 pa 值为 0
// 这里用到了条件运算符,条件运算符其实就是简化了的 if 语句,不懂自行百度一下。
}
// 基本操作一:查找(非递归版本)
int Findx(int x)
{
int y = x;
while (pa[y]!=0)// 寻找根
{
y = pa[y];
}
int root = y;// 保存根
int w;
y = x;// 复位
while (pa[y]!=0)// 执行路径压缩
{
w = pa[y];
pa[y] = root;
y = w;
}
return root;
}
void Union(int x, int y)
{
int u = Find(x);
int v = Find(y);
if (u==v) return;
if (rank[u]<=rank[v])// 按秩合并
{
pa[u] = v;
if (rank[u]==rank[v])// 树高相等时,合并后树会长高
rank[v]++;
}
else
{
pa[v] = u;
}
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for (int i=0; i<m; i++)
{
scanf("%d%d",&a,&b);
Union(a,b);
}
for (int i=0; i<p; i++)
{
scanf("%d%d",&a,&b);
int fa = Find(a);
int fb = Find(b);
if (fa!=fb) printf("No\n");
else printf("Yes\n");
}
return 0;
}
【Pascal版本】
const maxn=5000;
var i,n,m,p,mi,mj:integer;
father,height:array[1..maxn] of integer;{height数组记录集合的秩。所谓“秩”,只的是树的高度}
{并查集基本操作一:查找(非递归版本)}
function find(s:integer):integer;
var y,root,x:integer;
begin
{先从 s 出发往上找根}
y:=s;
while father[y]<>y do y:=father[y];
root:=y;
{回到 s,重新往根的方向走}
y:=s;
while father[y]<>y do begin{路径压缩}
x:=father[y];
father[y]:=root;
y:=x;
end;
find:=root;
end;
{并查集的基本操作之一:查找(递归版本)}
function findx(y:longint):longint;
begin
if father[y]=y then
exit(y)
else
begin
father[y]:=find(father[y]);{这里用递归的方式找根,也可以改用循环来实现}
exit(father[y]);
end;
end;
{并查集基本操作二:合并}
procedure merge(x,y:integer);
var u,v:integer;
begin
u:=find(x);
v:=find(y);
{按秩合并}
if height[u]<height[v] then father[u]:=v
else if height[u]>height[v] then father[v]:=u
else begin
father[u]:=v; height[v]:=height[v]+1;
end;
end;
begin
readln(n,m,p);
for i:=1 to n do father[i]:=i;
for i:=1 to n do height[i]:=1;
for i:=1 to m do begin
readln(mi,mj);
if find(mi)<>find(mj) then merge(mi,mj);
end;
for i:=1 to p do begin
readln(mi,mj);
if find(mi)=find(mj) then writeln('Yes') else writeln('No');
end;
end.

浙公网安备 33010602011771号