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.

 

posted @ 2013-12-19 19:30  莞中OI  阅读(185)  评论(0)    收藏  举报