poj 2524 Ubiquitous Religions 并查集

今天听了东哥的并查集的讲课,回忆起了以往的并查集的知识,自己在好好的写一把,仔细回忆一下自己理解的并查集;

并查集进行并和查的操作,对于这到信仰问题,只要知道每个节点的父节点就可以了,不用填加额外的信息。

Find(int i){
  if (father[i]==i)return i;
  father[i]=Find(father[i]);  //精辟的代码 进行了状态压缩 只要一次就能把之前的所有节点的父节点都对应好
  return father[i];         
}

Union(int a,int b){
    int fa=Father(a);     //寻找a的根节点 fa 
    int fb=Father(b);     // 寻找b的根节点 fb 
    if(fa!=fb){
        father[fa]=fb ;   //  fb成为了fa的父节点                    
    }
}

这是并查集的两段关键代码:

进行根节点的搜索和合并,注意搜索的时候用到了状态压缩使得合并操作不用再去比较树的秩的大小来确定根的合并方向,直接合并就好了。

Ubiquitous Religions 题目链接

贴代码:

#include<stdio.h>
#include<string.h>
int a[51000],sum;
int Find(int i){
    if(a[i]==i)return i;
    a[i]=Find(a[i]);
    return a[i];    
}
void Union(int numa,int numb){
   int fa=Find(numa);
   int fb=Find(numb);
   if(fa!=fb){
      a[fa]=fb;   //b是a的父节点  
      sum--;      //合并了就导致信仰少了一个。
   }
}

int main()
{
    int n,m,ji=0;
    while(scanf("%d%d",&n,&m)!=EOF){
         ji++;
         if( (n==0)  && (m==0))break;
         for(int i=1;i<=n;i++)
            a[i]=i;
         int num1,num2;
         sum=n;
         for(int i=1;i<=m;i++){
             scanf("%d%d",&num1,&num2);
             Union(num1,num2);       
         }
         printf("Case %d: %d\n",ji,sum);
    
    }
    
} 





你可能感兴趣的:(算法)