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

来源:互联网 发布:蓝牙单片机程序 编辑:程序博客网 时间:2024/05/14 14:39

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

初始化:

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

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<cnt;i++){father[save[i]]=x;}    return x;}


递归写法:

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 <iostream>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<k;j++)        {            if(z==cnt[j])            {                flag=1;                break;            }        }        if(!flag)        {            cnt[k++]=z;        }    }    return k-1;}int main(){    int n,m;    while(cin>>n>>m)    {        if(!n)            break;        Make_Set(n);        while(m--)        {            int x,y;            cin>>x>>y;            Union(x,y);        }        cout<<Cnt_Set(n)-1<<endl;    }    return 0;}


原创粉丝点击