poj 1611 The Suspects(第一道并查集)
题意:
有N个学生,编号为0-n-1,现在0号学生感染了非典,凡是和0在一个社团的人就会感染,
并且这些人如果还参加了别的社团,他所在的社团照样全部感染,社团个数为m,求感染的人数。
输入:
n代表人数,m代表社团数
社团的人数,第一个人编号,……
……
#include<stdio.h>
const int MAX=;
int n,m,k;
int parent[MAX+];
int total[MAX+];
//total[GetParent(a)] 是a所在的group的人数
int GetParent(int a)
{//获取a的根,并把a的父节点改为跟
if(parent[a]!=a)
parent[a]=GetParent(parent[a]);
return parent[a];
}
void Merge(int a,int b)
{
int p1=GetParent(a);
int p2=GetParent(b);
if(p1==p2)
return ;
total[p1]+=total[p2];
parent[p2]=p1;
}
int main()
{
int i,j;
while(true)
{
scanf("%d%d",&n,&m);
if(n==&&m==)break;
for(i=;i<n;i++)
{
parent[i]=i;
total[i]=;
}
for(i=;i<m;i++)
{
int h,s;
scanf("%d%d",&k,&h);
for(j=;j<k;j++)
{
scanf("%d",&s);
Merge(h,s);
}
}
printf("%d\n",total[GetParent()]);;
}
return ;
}
代码精炼版
摘自:Jack Ge for ACM
http://www.cnblogs.com/jackge/archive////.html
并查集学习:
l 并查集:(union-find sets)
一种简单的用途广泛的集合. 并查集是若干个不相交集合,能够实现较快的合并和判断元素所在集合的操作,应用很多,如其求无向图的连通分量个数等。最完美的应用当属:实现Kruskar算法求最小生成树。
l 并查集的精髓(即它的三种操作,结合实现代码模板进行理解):
1、MakeSet(x) 把每一个元素初始化为一个集合
初始化后每一个元素的父亲节点是它本身,每一个元素的祖先节点也是它本身(也可以根据情况而变)。
2、FindSet(x) 查找一个元素所在的集合
查找一个元素所在的集合,其精髓是找到这个元素所在集合的祖先!这个才是并查集判断和合并的最终依据。
判断两个元素是否属于同一集合,只要看他们所在集合的祖先是否相同即可。
合并两个集合,也是使一个集合的祖先成为另一个集合的祖先,具体见示意图
3、Union(x,y) 合并x,y所在的两个集合
合并两个不相交集合操作很简单:
利用Find_Set找到其中两个集合的祖先,将一个集合的祖先指向另一个集合的祖先。如图

l 并查集的优化
路径压缩
FindSet(x)寻找祖先时我们一般采用递归查找,但是当元素很多亦或是整棵树变为一条链时,每次Find_Set(x)都是O(n)的复杂度,有没有办法减小这个复杂度呢?
答案是肯定的,这就是路径压缩,即当我们经过"递推"找到祖先节点后,"回溯"的时候顺便将它的子孙节点都直接指向祖先,这样以后再次Find_Set(x)时复杂度就变成O(1)了,Union(x,y)
即合并的时候将元素少的集合合并到元素多的集合中,这样合并之后树的高度会相对较小。路径压缩方便了以后的查找。

#include<stdio.h>
const int maxn=;
int father[maxn];
int total[maxn];
void MakeSet(int n)
{
for(int i=; i<n; i++)
{
father[i]=i;
total[i]=;
}
}
int FindSet(int x)
{
if(x!=father[x])
father[x]=FindSet(father[x]);
return father[x];
}
void Union(int a,int b)
{
int x=FindSet(a);
int y=FindSet(b);
if(x==y)
return ;
if(total[x]>=total[y])
{
father[y]=x;
total[x]+=total[y];
}
else
{
father[x]=y;
total[y]+=total[x];
}
}
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
if(n==&&m==)
break;
int k,a,b;
MakeSet(n);
while(m--)
{
scanf("%d %d",&k,&a);
for(int i=; i<k; i++)
{
scanf("%d",&b);
Union(a,b);
}
}
printf("%d\n",total[father[]]);
}
return ;
}
poj 1611 The Suspects(第一道并查集)的更多相关文章
- poj 1611 :The Suspects经典的并查集题目
Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized ...
- POJ 1611 The Suspects(简单并查集)
( ̄▽ ̄)" #include<iostream> #include<cstdio> using namespace std; ]; void makeSet(int ...
- 【POJ】The Suspects(裸并查集)
并查集的模板题,为了避免麻烦,合并的时候根节点大的合并到小的结点. #include<cstdio> #include<algorithm> using namespace s ...
- FJUT寒假作业第三周数蚂蚁(记录第一道并查集)
http://210.34.193.66:8080/vj/Contest.jsp?cid=162#P7 思路:用并查集合并集合,最后遍历,找到集合的根的个数. 并查集是森林,森林中的每一颗树是一个集合 ...
- POJ 1611 The Suspects (并查集)
The Suspects 题目链接: http://acm.hust.edu.cn/vjudge/contest/123393#problem/B Description 严重急性呼吸系统综合症( S ...
- poj 1611 The Suspects 并查集变形题目
The Suspects Time Limit: 1000MS Memory Limit: 20000K Total Submissions: 20596 Accepted: 9998 D ...
- POJ 1611 The Suspects (并查集求数量)
Description Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, wa ...
- 并查集 (poj 1611 The Suspects)
原题链接:http://poj.org/problem?id=1611 简单记录下并查集的模板 #include <cstdio> #include <iostream> #i ...
- [并查集] POJ 1611 The Suspects
The Suspects Time Limit: 1000MS Memory Limit: 20000K Total Submissions: 35206 Accepted: 17097 De ...
随机推荐
- AVAWEB学习笔记 ---- 系列文章
[JAVAWEB学习笔记]网上商城实战5:后台的功能模块 [JAVAWEB学习笔记]网上商城实战4:订单模块 [JAVAWEB学习笔记]网上商城实战3:购物模块和订单模块 [JAVAWEB学习笔记]网 ...
- [转]HTTP 协议中的 Transfer-Encoding
本文作为我的博客「HTTP 相关」专题新的一篇,主要讨论 HTTP 协议中的 Transfer-Encoding.这个专题我会根据自己的理解,以尽量通俗的讲述,结合代码示例和实际场景来说明问题,欢迎大 ...
- MongoDB高级查询用法大全 (转)
http://www.cnblogs.com/t2xingzhe/p/3555268.html
- java内存基础(一)
博客园 闪存 首页 新随笔 联系 管理 订阅 随笔- 35 文章- 0 评论- 29 关于Java 数组内存分配一点认识 //总结:[ 数组引用变量存储在栈内存中,数组对象存储在堆内存当中.数 ...
- java代码求奖金。要求从键盘输入利润
总结:看似文字描述很多, package com.ai; import java.util.Scanner; import com.b.Scaner; //v企业发放的奖金根据利润提成.利润(I)低于 ...
- 分布式缓存系统 Memcached CAS协议
Memcached在1.2.4版本后新增了CAS(Check and Set)协议,主要用于并发控制:memcached中同一个item同时被多个线程(多个客户端)更改的并发问题.CAS协议最本质的东 ...
- C#获取网络状态
/// <summary> /// 获取网络状态 /// </summary> /// <param name="ip">目标IP地址</ ...
- js实现的点击div区域外隐藏div区域
首先看下JS的事件模型,JS事件模型为向上冒泡,如onclick事件在某一DOM元素被触发后,事件将跟随节点向上传播,直到有click事件绑定在某一父节点上,如果没有将直至文档的根. 阻止冒泡:1.对 ...
- Python——Dict
Python字典(Dictionary) 字典是一种可变容器模型,可存储任意类型对象. 字典的每个键值(key => value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花 ...
- [转]C#开发微信公众平台-就这么简单
本文转自:http://www.it165.net/pro/html/201403/11102.html 写在前面 服务号和订阅号 URL配置 创建菜单 查询.删除菜单 接受消息 发送消息(图文.菜单 ...