POJ 1611 ACM数据结构The Suspects (并查集)
2016-05-25 17:30
423 查看
题目描述:
有很多组学生,在同一个组的学生经常会接触,也会有新的同学的加入。但是SARS是很容易传染的,只要在该组有一位同学感染SARS,那么该组的所有同学都被认为得了SARS。现在的任务是计算出有多少位学生感染SARS了。假定编号为0的同学是得了SARS的。
#include <stdio.h>
#include <iostream>
using namespace std;
const int MAXN = 30001; /*结点数目上线*/
int pa[MAXN]; /*p[x]表示x的父节点*/
int rank[MAXN]; /*rank[x]是x的高度的一个上界*/
int num[MAXN];/*num[]存储该集合中元素个数,并在集合合并时更新num[]即可*/
void make_set(int x)
{
pa[x] = x;
rank[x] = 0;
num[x] = 1;
}
int find_set(int x)
{/*带路径压缩的查找*/
/*保存待查找的数*/
int r = x, temp;
/*找到根节点*/
while(pa[r] != r) r = pa[r];
while(x != r)
{
temp = pa[x];
pa[x] = r;
x = temp;
}
return x;
//if(x != pa[x]) //注释掉的其实也是可以的,不过不想用递归来做啦
// pa[x] = find_set(pa[x]);
//return pa[x];
}
/*按秩合并x,y所在的集合*/
void union_set(int x, int y)
{
x = find_set(x);
y = find_set(y);
if(x == y)return ;
if(rank[x] > rank[y])/*让rank比较高的作为父结点*/
{
pa[y] = x;
num[x] += num[y];
}
else
{
pa[x] = y;
if(rank[x] == rank[y])
rank[y]++;
num[y] += num[x];
}
}
//answer to 1611
int main()
{
int n, m, x, y, i, t, j;
while(scanf("%d%d", &n, &m))
{
if(m==n && n == 0) break;
if(m == 0)
{
cout << "1\n"; continue;
}
for(i = 0; i < n; i++)
make_set(i);
for(i = 0; i < m; i++)
{
scanf("%d", &t);
scanf("%d", &x);
for(j = 1; j < t; j++){
scanf("%d", &y);
union_set(x, y);
x = y;
}
}
x = find_set(0);/*找到0所在的树的树根*/
//int ans = 0;
//for(i = 0; i < n; i++)
// if(pa[i] == x)
// ans++;
//cout << ans << endl;
cout << num[x] << endl;
}
return 0;
}
有很多组学生,在同一个组的学生经常会接触,也会有新的同学的加入。但是SARS是很容易传染的,只要在该组有一位同学感染SARS,那么该组的所有同学都被认为得了SARS。现在的任务是计算出有多少位学生感染SARS了。假定编号为0的同学是得了SARS的。
#include <stdio.h>
#include <iostream>
using namespace std;
const int MAXN = 30001; /*结点数目上线*/
int pa[MAXN]; /*p[x]表示x的父节点*/
int rank[MAXN]; /*rank[x]是x的高度的一个上界*/
int num[MAXN];/*num[]存储该集合中元素个数,并在集合合并时更新num[]即可*/
void make_set(int x)
{
pa[x] = x;
rank[x] = 0;
num[x] = 1;
}
int find_set(int x)
{/*带路径压缩的查找*/
/*保存待查找的数*/
int r = x, temp;
/*找到根节点*/
while(pa[r] != r) r = pa[r];
while(x != r)
{
temp = pa[x];
pa[x] = r;
x = temp;
}
return x;
//if(x != pa[x]) //注释掉的其实也是可以的,不过不想用递归来做啦
// pa[x] = find_set(pa[x]);
//return pa[x];
}
/*按秩合并x,y所在的集合*/
void union_set(int x, int y)
{
x = find_set(x);
y = find_set(y);
if(x == y)return ;
if(rank[x] > rank[y])/*让rank比较高的作为父结点*/
{
pa[y] = x;
num[x] += num[y];
}
else
{
pa[x] = y;
if(rank[x] == rank[y])
rank[y]++;
num[y] += num[x];
}
}
//answer to 1611
int main()
{
int n, m, x, y, i, t, j;
while(scanf("%d%d", &n, &m))
{
if(m==n && n == 0) break;
if(m == 0)
{
cout << "1\n"; continue;
}
for(i = 0; i < n; i++)
make_set(i);
for(i = 0; i < m; i++)
{
scanf("%d", &t);
scanf("%d", &x);
for(j = 1; j < t; j++){
scanf("%d", &y);
union_set(x, y);
x = y;
}
}
x = find_set(0);/*找到0所在的树的树根*/
//int ans = 0;
//for(i = 0; i < n; i++)
// if(pa[i] == x)
// ans++;
//cout << ans << endl;
cout << num[x] << endl;
}
return 0;
}
相关文章推荐
- 数据结构实验5-2
- C/C++、JAVA 数据结构 :双向循环链表
- 字符串操作
- Poj 3320 acm 数据结构 哈希表入门
- 数据结构实验-用C++实现带头结点的循环链表
- java数据结构-Vector
- 【数据结构学习】二叉树
- HDU1702 acm 数据结构 ACboy needs your help again!
- HDU1022 acm 数据结构 Train Problem I
- 每天一点数据结构之二叉树的插入与创建
- 浅谈算法和数据结构: 九 平衡查找树之红黑树
- 数据结构[刷水]
- 《数据结构》3.1双栈--按栈号进行操作
- 常用的数据结构算法
- 《数据结构》3.1双栈结构
- C++ map,set内部数据结构
- 数据结构->冒泡排序
- 数据结构基础之循环队列C语言实现
- 《 常见算法与数据结构》平衡查找树(2)——红黑树(附动画)
- 《 常见算法与数据结构》平衡查找树(1)—— 2-3查找树(附动画)