解题报告-HDOJ-1232(并查集)

并查集是一种树形数据结构,一般用来处理一些不相交集合的合并和查询。一般有如下操作:

初始化:

将集合中的所有点初始化为自身,表示该点为一个单独的集合。

void Make_Set(int x)
{//初始化
    for(int i=1;i<=x;i++)
    {
        father[i]=i;
        rank[i]=0;
    }
}

 

查找:

查找两个点是否在同一个集合中。

非递归:

int Find_Set(int x)
{//查找
    while(father[x]!=x)
    {
        x=father[x];
    }
    return x;
}

优化(压缩路径):

定义一个保存路径的save数组.

int Find_Set(int x)
{//查找
    int cnt=0;
	int save[MAXN];
    while(father[x]!=x)
    {
		save[cnt ++]=a;
        x=father[x];
    }
	for(int i=0;i


递归写法:

int Find_Set(int x)
{//查找
    if(father[x]!=x)
	{
		father[x]=Find_set(father[x]);
	}
    return father[x];
}

合并:

将两个不相交的集合合并为一个集合。

void Union(int x,int y)
{//合并
    x=Find_Set(x);
    y=Find_Set(y);
    if(x==y) return;
        father[x]=y;
}

 

优化:

用rank数组保存树的高度,把矮树并到高的树上。

 

#include 
using namespace std;
const int MAXN=1000+50;
int father[MAXN];
int sign[MAXN];
int rank[MAXN];
int cnt[MAXN];//保存不同集合的根节点

void Make_Set(int x)
{//初始化
    for(int i=1;i<=x;i++)
    {
        father[i]=i;
        rank[i]=0;
    }
}
int Find_Set(int x)
{//查找
    int i=0;
    while(father[x]!=x)
    {
        sign[i++]=x;
        x=father[x];
    }
    for(;i>0;i--)
    {
        father[sign[i-1]]=x;
    }
    return x;
}
void Union(int x,int y)
{//合并
    x=Find_Set(x);
    y=Find_Set(y);
    if(x==y) return;
    if(rank[x]>rank[y])
    {
        father[y]=x;
    }
    else if(rank[x]==rank[y])
    {
        father[x]=y;
        rank[y]++;
    }
    else
    {
        father[x]=y;
    }
}
int Cnt_Set(int x)
{//统计不同的集合数
    int k=1;
    cnt[k++]=Find_Set(1);
    for(int i=2;i<=x;i++)
    {
        int flag=0;
        int z=Find_Set(i);
        for(int j=1;j>n>>m)
    {
        if(!n)
            break;
        Make_Set(n);
        while(m--)
        {
            int x,y;
            cin>>x>>y;
            Union(x,y);
        }
        cout<


你可能感兴趣的:(HDOJ结题报告,数据结构)