The Suspects(POJ - 1611)并查集
2017-08-07 19:15
489 查看
一、题目大意
有n个人和m个小组,不同小组之间的人员可以重复,人员编号从0-n-1。
现流行一种传染病,只要小组内有一个人患病,组内所有人都将被感染患病。
现在0号人员患病,求被感染患病的总人数。
二、思路分析
我一开始的思路是,给定组内成员编号,相邻的两位成员,两两合并到一个集合。
需要注意的是要路径压缩,本题数据量较大,路径压缩后复杂度将为阿克曼函数的反函数。
三、附代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstring>
#include<string>
#include<set>
#include<cmath>
#include<map>
#include<sstream>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long LL;
const int maxn = 30000 + 8;
int n,m,t;
int par[maxn],po[maxn];
int Find(int a)
{
return a == par[a] ? a : par[a] = Find(par[a]);
}
void Unite(int a,int b)
{
a = Find(a);
b = Find(b);
if(a == b) return;
par[b] = a;
}
int main()
{
while(scanf("%d%d",&n,&m) == 2 && (m || n))
{
set<int> p;
memset(par, 0, sizeof par);
for (int i = 0; i < n; ++i) par[i] = i;
bool flag = false;
while(m--)
{
memset(po, 0, sizeof po);
cin >> t;
for (int i = 0; i < t; ++i) {
cin >> po[i];
p.insert(po[i]);
if(po[i] == 0) flag = true;
}
if (t >= 1) {
for(int i = 0; i < t-1; ++i){
Unite(po[i],po[i+1]);
}
/*for (int i = 1; i < t; ++i) {
Unite(po[0], po[i]);
}*/
}
}
if(!flag){
cout << 1 << endl;
continue;
}
set<int>::iterator it;
int ans = 0;
int root = Find(0);
//cout << root << endl;
/*for(it = p.begin(); it != p.end(); ++it){
cout << *it << " " << par[*it] << endl;
}*/
for(it = p.begin(); it != p.end(); ++it){
if(Find(*it) == root){
ans++;
}
}
cout << ans << endl;
}
return 0;
}
/*
10 2
5 0 1 2 3 4
4 5 3 6 7
0 0
0 5
1 0
2 0
3 5
4 0
5 5
6 5
7 5
8
*/
有n个人和m个小组,不同小组之间的人员可以重复,人员编号从0-n-1。
现流行一种传染病,只要小组内有一个人患病,组内所有人都将被感染患病。
现在0号人员患病,求被感染患病的总人数。
二、思路分析
我一开始的思路是,给定组内成员编号,相邻的两位成员,两两合并到一个集合。
需要注意的是要路径压缩,本题数据量较大,路径压缩后复杂度将为阿克曼函数的反函数。
三、附代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstring>
#include<string>
#include<set>
#include<cmath>
#include<map>
#include<sstream>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long LL;
const int maxn = 30000 + 8;
int n,m,t;
int par[maxn],po[maxn];
int Find(int a)
{
return a == par[a] ? a : par[a] = Find(par[a]);
}
void Unite(int a,int b)
{
a = Find(a);
b = Find(b);
if(a == b) return;
par[b] = a;
}
int main()
{
while(scanf("%d%d",&n,&m) == 2 && (m || n))
{
set<int> p;
memset(par, 0, sizeof par);
for (int i = 0; i < n; ++i) par[i] = i;
bool flag = false;
while(m--)
{
memset(po, 0, sizeof po);
cin >> t;
for (int i = 0; i < t; ++i) {
cin >> po[i];
p.insert(po[i]);
if(po[i] == 0) flag = true;
}
if (t >= 1) {
for(int i = 0; i < t-1; ++i){
Unite(po[i],po[i+1]);
}
/*for (int i = 1; i < t; ++i) {
Unite(po[0], po[i]);
}*/
}
}
if(!flag){
cout << 1 << endl;
continue;
}
set<int>::iterator it;
int ans = 0;
int root = Find(0);
//cout << root << endl;
/*for(it = p.begin(); it != p.end(); ++it){
cout << *it << " " << par[*it] << endl;
}*/
for(it = p.begin(); it != p.end(); ++it){
if(Find(*it) == root){
ans++;
}
}
cout << ans << endl;
}
return 0;
}
/*
10 2
5 0 1 2 3 4
4 5 3 6 7
0 0
0 5
1 0
2 0
3 5
4 0
5 5
6 5
7 5
8
*/
相关文章推荐
- POJ 1611 The Suspects(并查集求集合的基数)
- [ACM] POJ 1611 The Suspects (并查集,输出第i个人所在集合的总人数)
- POJ 1611 The Suspects (并查集III)
- POJ - 1611-The Suspects(并查集)
- POJ 1611 The Suspects(并查集)
- POJ 1611 The Suspects (并查集)
- POJ 1611 The Suspects(并查集)
- poj 1611 The Suspects(并查集)
- POJ 1611 The Suspects(并查集)
- poj-1611-The Suspects(水并查集)
- POJ 1611 The Suspects(带权并查集)
- POJ 1611 The Suspects(并查集)
- poj 1611-The Suspects:并查集
- poj-1611-The Suspects(并查集)
- POJ 1611 The Suspects(并查集模板)
- POJ-1611-The Suspects(并查集)
- [并查集]POJ 1611 The Suspects
- poj 1611-The Suspects:并查集
- poj 1611 The Suspects(并查集)
- kuangbin专题五 并查集 POJ-1611 The Suspects