More is better - 九度 OJ 1444

More is better - 九度 OJ 1444

题目

时间限制:1 秒 内存限制:100 兆 特殊判题:否
题目描述:
Mr Wang wants some boys to help him with a project. Because the project is rather complex, the more boys come, the better it will be. Of course there are certain requirements.Mr Wang selected a room big enough to hold the boys. The boy who are not been chosen has to leave the room immediately. There are 10000000 boys in the room numbered from 1 to 10000000 at the very beginning. After Mr Wang’s selection any two of them who are still in this room should be friends (direct or indirect), or there is only one boy left. Given all the direct friend-pairs, you should decide the best way.
输入:
The first line of the input contains an integer n (0 ≤ n ≤ 100 000) - the number of direct friend-pairs. The following n lines each contains a pair of numbers A and B separated by a single space that suggests A and B are direct friends. (A ≠ B, 1 ≤ A, B ≤ 10000000)
输出:
The output in one line contains exactly one integer equals to the maximum number of boys Mr Wang may keep.
样例输入:
4
1 2
3 4
5 6
1 6
4
1 2
3 4
5 6
7 8
样例输出:
4
2

题目大意:有1000 0000个小朋友,他们之中有N对好朋友,且朋友关系具有传递性:若A与B是朋友,B与C是朋友,那么也认为A与C是朋友。 在给出这 N 对朋友关系后,要求找出一个最大(人数最多)的集合,该集合中任意两人之间都是朋友或者该集合中只有一个人,输出该最大人数。
利用并查集相关操作已经可以求得有几个这样符合条件的集合,但是计算集合中的元素个数仍没有涉及。如果能够成功求得每个集合的元素个数,只需要选择包含元素最多的集合,并输出该集合中的元素个数即可。
为了计算每个集合的元素个数,不妨在表示每个集合的树的根结点记录该集合所包含的元素个数,在合并时累加被合并两个集合包含的元素个数。最后, 找出所有集合中所包含元素最多的集合即是所求。

#include <stdio.h>
#define N 10000001
using namespace std;

int Tree[N];

int findRoot(int x){
    if(Tree[x]==-1)return x;
    else{
        int tmp=findRoot(Tree[x]);
        Tree[x]=tmp;
        return tmp;
    }
}

int sum[N];
//用sum[i]表示以节点i为根的树的节点个数
//其中保存数据仅当Tree[i]为-1即该节点为树的根节点时有效

int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<N;i++){
            //初始化节点信息
            Tree[i]=-1;//所有节点为孤立集合
            sum[i]=1;//所有集合的元素个数为1
        }
        while(n--){
            int a,b;
            scanf("%d%d",&a,&b);
            a=findRoot(a);
            b=findRoot(b);
            if(a!=b){
                Tree[a]=b;
                sum[b]+=sum[a];
                //合并两集合时,将成为子树的树的根节点上
                //保存的该集合元素个数累加到合并后的新树的树根
            }
        }
        int ans=1;//答案,至少为1
        for(int i=1;i<=N;i++){
            if(Tree[i]==-1 && sum[i]>ans)ans=sum[i];
            //统计最大值
        }
        printf("%d",ans);
    }
    return 0;
}

在使用并查集的同时也可以在表示集合的 树的根结点保存其它额外信息,并且在集合合并的过程中维护该值,以便于求解某些集合问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值