好久没做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 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;
}
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;
}