超有爱的并查集~ mark
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int pre[1010]; //里面全是掌门
int unionsearch(int root)
{
int son, tmp;
son = root;
while(root != pre[root]) //寻找掌门ing……
root = pre[root];
while(son != root) //路径压缩
{
tmp = pre[son];
pre[son] = root;
son = tmp;
}
return root; //掌门驾到~
}
int main()
{
int num, road, total, i, start, end, root1, root2;
while(scanf("%d%d", &num, &road) && num)
{
total = num - 1; //共num-1个门派
for(i = 1; i <= num; ++i) //每条路都是掌门
pre[i] = i;
while(road--)
{
scanf("%d%d", &start, &end); //他俩要结拜
root1 = unionsearch(start);
root2 = unionsearch(end);
if(root1 != root2) //掌门不同?踢馆!~
{
pre[root1] = root2;
total--; //门派少一个,敌人(要建的路)就少一个
}
}
printf("%d\n", total);//天下局势:还剩几个门派
}
return 0;
}
int par[max_n]; //父亲
int rank[max_n] //树的高度
//par[i]里面的i代表是第i个元素,par[i]里面存的值代表的是i元素的上级
//初始化n个元素
void init(int n)
{
for(int i=0;i<n;i++)
{
par[i]=i;
rank[i]=0;
}
}
//查询树的根
int find(int x)
{
if(par[x]==x)
return x;
else
return par[x] =find(par[x]); //直到该x找到最大boss 状态压缩
}
//合并x和y所属的集合
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y) return;
if(rank(x)<rank[y])
par[x]=y;
else
par[y]=x;
if(rank[x]==rank[y]) rank[x]++;
}
//判断x和y是否属于一个集合
bool same(int x,int y)
{
return find(x)==find(y);
}