ACM简单题目--并查集

好久没做ACM了(话说当年做的时候也很酱油的..),最近学校举办“华为杯”程序设计竞赛,怀念起当年的编程岁月(唉,人已老,物是人非了..),于是决定再做个题目,才能对得起自己,还好题目比较简单,轻松AC了一个,写下解题报告,是并查集应用的题目。

原题描述:http://jol.seu.edu.cn/JudgeOnline/problem.php?id=52

52: 校赛题:DG之社团调查

时间限制: 1 Sec   内存限制: 128 MB
提交: 789   解决: 76
[ 提交][ 状态][ 讨论版]

题目描述

自从进了大学,DG发现周围所有的同学几乎都进了社团,他十分想知道同学们究竟都参加了多少个不同的社团。但是DG觉得直接问同学参加了什么社团不够礼貌,因为那样就显得自己对同学不够关心了解。于是聪明的DG想到了另外一种问法:“A和B是否是同一个社团?”。这样一来虽然DG不能直接得到同学参加社团的信息,但是他可以从这次些关系中统计出周围人所参与的社团的个数(假如每个同学最多只能参加一个社团,没有人参加的社团不用考虑)。要么,你也来试一试?

输入

输入包含多组测试数据;
每组测试数据的第一行包含两个整数n,m。其中n表示总人数。接下来有m行,每行有两个整数i,j,表示i,j两人同属于一个社团; (0 < n <= 50000,0 <= m <= n(n-1)/2)
当n=m=0时输入结束。

输出

对于每组测试样例输出一行,表示被询问到的人最多参加了多少个不同的社团。

样例输入

10 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
10 4
2 3
4 5
4 8
5 8
0 0

样例输出

1
7


分析:该题目是简单的并查集应用问题,关于并查集,请参考博客http://dongxicheng.org/structure/union-find-set/  学习

解题思路:初始相应的数组,让每个人为一个集合,读取一组样例输入,判断两个人是否是在同一集合,若在,则直接跳过,否则合并两个集合,并减少最大参加社团的个数,附AC程序代码:
#include<iostream>
using namespace std;  
 
const int MAX = 50010;  
int father[MAX],sp[MAX];

void init_set(int n){   
    for (int i = 1; i <= n; i++)
    {
        father[i] = i;
        sp[i] = i;
    }
}  

int Find_Set(int x){  
    if (x != father[x])
    {
        father[x] = Find_Set(father[x]);
    }

    return father[x];
}
 

void Union(int x, int y)
{
    x = Find_Set(x);
    y = Find_Set(y);
    if (x == y) return;
    if (sp[x] < sp[y])
    {
        father[y] = x;
    }
    else
    {
        father[x] = y;
    }
}

int main()
{
    int m,n;
    int a,b;
    while(cin>>m>>n)
    {
        if(m==0&&n==0)
            break;
        int count = m;
        init_set(m);
        for(int i=1;i<=n;i++)
            {
                cin>>a>>b;
                if(Find_Set(a)!=Find_Set(b))
                {
                    Union(a,b);
                    count--;
                }
        }

        cout<<count<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值