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 ...
随机推荐
- centos6.5 安装sftp
1.创建sftp组 : groupadd sftp 2.创建一个sftp用户,用户名为andy : useradd -g sftp -s /bin/false andy 3.修改密码: pas ...
- ①HttpURLConnection通过报文提交
在进行短信发送的接口,因厂家不同,有的厂家会采用报文的格式进行短信请求的发送与接收.本文主要介绍利用HttpURLConnection进行短信报文的请求与响应. 一般的url请求分为两种,一种是GET ...
- 配置动态ip为静态ip qq交流总结
修改 /etc/sysconfig/network-scripts/ifcfg-etho 修改dhcp 为 static 修改后的样例 这三个ip该怎么对应 ifconfig 123各自对应 修改/e ...
- java随机数组
import java.util.Random; public class Ccore { public static void main(String[] args) { for(int i=1;i ...
- java练习篇 求输出最大值
总结:没有把数据输入.是数组-----把要输入的数据放在数组里.错在这里 import java.util.Scanner; public class shibai { public static v ...
- 几种经典的hash算法
计算理论中,没有Hash函数的说法,只有单向函数的说法.所谓的单向函数,是一个复杂的定义,大家可以去看计算理论或者密码学方面的数据.用“人 类”的语言描述单向函数就是:如果某个函数在给定输入的时候,很 ...
- xunsearch全文检索初体验
目录 测试添加数据 测试搜索 简单搜索 稍微复杂的搜索 搜索建议 测试添加数据 ./Indexer.php --source=csv --clean demo 清空现有索引数据 ... 初始化数据源 ...
- PHP 获取指定日期的星期几的方法
<?php header("Content-type: text/html; charset=utf-8"); //获取星期方法 function get_week($dat ...
- 五 搭建kafka集群
1 下载 wget http://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.0.0/kafka_2.12-2.0.0.tgz 2 tar -zxv ...
- IDA Pro 权威指南学习笔记(一) - 启动 IDA
启动 IDA 启动 IDA,有一个欢迎界面 之后有一个对话框 选择 New 将启动一个对话框来选择将要分析的文件 选择 Go 将使 IDA 打开一个空白的工作区 如果要选择分析的文件,可以直接拖到 I ...