题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1856
这道题目的目的是想知道经过一系列的合并操作之后,查询在所有的子树中,秩的最大值是多少,简而言之,就是最大的那颗子树包含了多少个节点。
很显然,这个问题也能够同时使用两种优化策略,只不过因为要求最大秩的值,需要有一个变量来记录。那么在哪个地方来更新它是最好的呢?我们知道,在按秩进行合并的时候,需要比较两颗待合并子树的秩,因此可以顺带的将对秩的最大值的更新也放在这里进行
/*不是求有几个集合,而是求每个集合中元素的个数,进而求出个数的最大值。
和求集合个数的方法差不多,只需要在合并两个集合时处理一下,让这两个集合的元素个数也合并一下就行了。
接下来只需要找出最大值即可。要注意的一个地方就是:当n=0时,要输出1。
*/
#include<stdio.h>
#define N 10000000
int father[N],num[N];
void initial()/*初始化*/
{
int i;
for(i=1;i<=N;i++)
{
father[i]=i;
num[i]=1;/*开始时数量都为1,根节点为自己*/
}
}
int find(int x) /*寻找根节点*/
{
if(father[x]!=x)
father[x]=find(father[x]);
return father[x];
}
void merge(int a,int b)/*合并a和b*/
{
int p=find(a);
int q=find(b);
if(p!=q)
{
father[p]=q;
num[q]+=num[p];/*合并集合中元素个数*/
}
}
int main()
{
int n,a,b,i,sum,max;
while(~scanf("%d",&n))
{
if(n==0)
{
printf("1\n");
continue;
}
max=0;
initial(); /*初始化*/
for(i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
if(a>max)
max=a;
if(b>max)
max=b;
merge(a,b); /*合并集合*/
}
int Max=0;
for(i=1;i<=max;i++)
if(num[i]>Max) /*查找最大值*/
Max=num[i];
printf("%d\n",Max);
}
return 0;
}