并查集的例题

来源:互联网 发布:淘宝推广返利网 编辑:程序博客网 时间:2024/05/11 12:04

/*题意为: 已知学校有n个学生 ,想知道有多少个宗教,但是不能一个一个问学生   ,已知两个一起的是一个宗教的,现可以问m对学生,请求出最多有多少个宗教    输入数据  10   4          2   3   4   5   4   8    5   8    答案为7                由题知采用并查集求解 (可看做二叉树 )     */

#include<iostream>

using namespace  std;


//const  int max = 5005;
int pa[1000];            //定义数组,用来存储结点
int rank[1000];          //定义秩,即某一个结点可容纳的结点数  
int ans;                                  //答案


void set(int x)                   //初始化每个结点,是自己就是一个根结点
{
pa[x] = x;
rank[x] = 0;
}


int find(int x)   //寻找结点的根
{
if (x != pa[x])              //判断自己的根结点是否是自己
{
pa[x] = find(pa[x]);
}
return pa[x];                       //返回找到的根结点
}


void  Union(int x, int y)  //联合函数 ,把两个结点连接起来
{
x = find(x);                         //先找到根结点
y = find(y);
if (x == y) //判断是否相等,如果相等就不用操作
{
return;
}
ans--;      //如果是相等的,则宗教总数就会少一
if (rank[x] > rank[y])//看谁的秩大,即已经拥有的结点多,把稍等放在多的下面,为了减低树的高度,查找时方便
{
pa[y] = x;
}
else
{
pa[x] = y;
if (rank[x] == rank[y])
{
rank[y]++;
}
}
}


int main()
{
int m,n; 
int i;
while ((cin>>n,cin>>m)&&(n>0,m>=0))
{
for (i = 1; i <=n;i++)            //对每个都进行初始化
{
set(i);
}
ans = n;
int person1, person2;  
for (i = 0; i < m; i++)
{
cin >> person1 >> person2;  //输入两个要询问的对象
Union(person1, person2);      //联合
}
int k = 1;
cout <<"case" <<k<<":"<<ans<< endl;
k++;
cin >> n >> m;
}


return 0;
}
0 0
原创粉丝点击