算法手记 之 数据结构(并查集详解)(POJ1703)
《ACM/ICPC算法训练教程》读书笔记-这一次补上并查集的部分。将对并查集的思想进行详细阐述,并附上本人AC掉POJ1703的Code。
在一些有N个元素的集合应用问题中,通常会将每个元素构成单元素集合,然后按照一定顺序将同属一组的集合合并,期间要反复查找每一个元素在哪个集合中。这类问题往往看似简单,但是数据量很大,因此容易造成TLE或MLE,也就是空间度和时间度极其复杂。因此在这里,我们引入一种抽象的特殊数据结构——并查集。
并查集:类似一个族谱,每个结点均有一个father[x]来表示x结点的父结点,因此,我们在给并查集初始化的时候,先将结点设为自己的父结点,也就是: father[x] = x; ,依次初始所有结点。
并查集有两种重要的操作:查找,合并。
查找
并查集为避免时间上和空间上的损耗,在每一轮查找时,都要进行一次路径压缩优化。什么叫做路径压缩呢,简单的说就是将所有子结点都直接归属其根结点,减小代差,这样父辈和子辈就方便"交流"了。
具体来说,在查找时,如果得到3的父结点为1,而1的父结点为2,2的父结点又为4,就依次完成: father[3] = father[1] = father[2] = 4;
这样的优势就在于待到下一次查找时,可以直接进行一次操作完成查询,而不需多次操作“寻根问底”。
在这里我们利用递归的思想让这段代码实现起来简便易行:
/*查找并压缩路径*/
int Find_set(int x)
{
int temp = fa[x];
if(x != fa[x])
fa[x] = Find_set(fa[x]); //路径压缩
return fa[x];
}
/*使用*/
p[x] = Find_set(x);
合并
也就是合并x和y所在的两个集合,简单来说,只需要把其中一个集合的根节点赋给另一个集合的根节点就可以了。因此此时需要进行一次查询操作并查找到x和y所在集合的两个根节点。
具体实现如下:
void Union(int x,int y)
{
int fx = Find_set(x);
int fy = Find_set(y);
if (fx == fy) //根节点Same
return;
father[fx] = fy;
}
本书在这里给出的Code包括了启发式合并:也就是将深度小的根节点挂在深度大的根节点上,这样每次查询时进行路径压缩的次数就会得到优化。
但是我认为初学的时候摊上这个就有点麻烦了,而且这种优化在一定程度来说写起来比较繁琐,因此就没有在这里贴出来了,在某些极端情况下可以加上启发式合并试试。
那么像这样利用路径压缩就可以将并查集的时间复杂度看做O(1),空间复杂度为O(n),这样就将一个大规模问题转化为一个空间小,速度极快的简单操作。
POJ1703解题报告:
题目大意:Tadu City中有两个黑帮团伙,一共n名团伙成员(不知道属于哪个组织),现在警察局有一些信息,每条信息包括两个人的编号:
输入D x y:代表x于y不在一个团伙里
输入A x y:询问x与y是否在同一团伙或者不确定他们在同一个团伙里
那么在这种题目中,我们用并查集的思想可以避免大规模地遍历每个成员。那么具体来说如何实现呢。
如果定义两个帮派集合,那么在大量的D x y中也可能无法确认谁属于哪个帮派,而如果定义每个人一个帮派,那么就可以将并查集的思想利用起来,为了表明成员间的关系,因此我们在这里加入一个relate[x]来表明x结点与其父结点的关系。我们用1来表示这两个成员是不同帮派,而用0来表示这两个成员属于同一个帮派。
大家可以先打个草稿来尝试如何将大量D x y数据合并(注意relate[]的调整)
Code仅供参考:
//并查集:D x y 表示x和y分属不同帮派,A x y表示查询x和y的关系
//在并查集的基础上加上relate[],表示t与其父结点fa[t]的关系
//Memory:948K Time:344Ms
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAX 100005
int n, m;
int fa[MAX], r[MAX]; //father node - relation
int find(int x)
{
if (x != fa[x]) {
int pa = fa[x];
fa[x] = find(fa[x]); //路径压缩
r[x] ^= r[pa]; //改变关系
}
return fa[x];
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
memset(r, , sizeof(r));
for (int i = ; i <= n;i++)
fa[i] = i;
while (m--)
{
int c1, c2;
char flag;
scanf("\n%c%d%d", &flag, &c1, &c2);
//找出根节点
int p1 = find(c1), p2 = find(c2);
if (flag == 'A')
{
if (p1 != p2)
printf("Not sure yet.\n");
else if (r[c1] == r[c2])
printf("In the same gang.\n");
else printf("In different gangs.\n");
}
else {
fa[p1] = p2;
r[p1] = r[c1] == r[c2]; //c1-p1与c2-p2关系相同则p1与p2关系不同,反之亦然
}
}
}
return ;
}
算法手记 之 数据结构(并查集详解)(POJ1703)的更多相关文章
- - > 并查集详解(第二节)
以下是并查集思路详解: 一:概念 并查集处理的是“集合"之间的关系.当给出两个元素的一个无序数对(a,b)时,需要快速“合并”a和b分别所在的集合,这期间需要反复“查找”某元素所在的集合.“ ...
- 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用
图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...
- ACM数据结构-并查集
ACM数据结构-并查集 并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合 ...
- 【算法导论-36】并查集(Disjoint Set)具体解释
WiKi Disjoint是"不相交"的意思.Disjoint Set高效地支持集合的合并(Union)和集合内元素的查找(Find)两种操作,所以Disjoint Set中文翻译 ...
- 图论&数据结构——并查集
Wikioi 4246 NOIP模拟赛Day2T1 奶牛的身高 题目描述 Description 奶牛们在FJ的养育下茁壮成长.这天,FJ给了奶牛Bessie一个任务,去看看每个奶牛场中若干只奶牛的 ...
- POJ 1703 Find them, Catch them (数据结构-并查集)
Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 31102 Accepted: ...
- 《挑战程序设计竞赛》2.4 数据结构-并查集 POJ1182 2236 1703 AOJ2170
POJ1182 http://poj.org/problem?id=1182 题目 难得的中文题... 食物链 Time Limit: 1000MS Memory Limit: 10000K Tota ...
- 算法笔记--可撤销并查集 && 可持久化并查集
可撤销并查集模板: struct UFS { stack<pair<int*, int>> stk; int fa[N], rnk[N]; inline void init(i ...
- 第三十一篇 玩转数据结构——并查集(Union Find)
1.. 并查集的应用场景 查看"网络"中节点的连接状态,这里的网络是广义上的网络 数学中的集合类的实现 2.. 并查集所支持的操作 对于一组数据,并查集主要支持两种操作:合并两 ...
随机推荐
- JaxWsProxyFactoryBean 与 JaxWsDynamicClientFactory
1. JaxWsProxyFactoryBean 简介:调用方式采用了和RMI类似的机制,即客户端直接调用服务器端提供的服务接口(interface),CXF通过运行时代理生成远程服务的代理对象 ...
- centos 安装 mysql5.7.9初始密码问题
mysql5.7.9在安装完成后会,root用户会产生一个不为空的初始密码,登陆mysql就会产生问题了,有必要修改一下登陆密码: 这是从网上找的一个方法,加以总结得出来的,亲测可以:# /etc/i ...
- Ubuntu 16.10 虚拟机安装记录
一定要选自定义. 这里一定要选 稍后安装操作系统 都是坑! 启动时出现'SMBus Host Controller not enabled'错误提示,进不到图形界面. 解决办法:1.在启动Ubunt ...
- flask 知识点总结
============================request对象的常用属性============================具体使用方法如下:request.headers, requ ...
- fullPage 全屏滚动【上下滚动】效果
由于个人能力,研究了两天,终于写出来了. 又花了一天的时间成功的将30多行脚本,改成了70多行,我也是够有心的了. 那么接下来就是我制作这个效果的全部过程. 那一年我十七,她十八,在那个夏天里,我们, ...
- IIS服务器运行一段时间后卡死,且无法打开网站(IIS管理无响应,必须重启电脑)
问题描述: 公司希望使用IIS配合网站显示一些订单跟进的情况并展示出来,所以我们在一台演示的Win7 Pro电脑上安装了IIS,但使用了一段时间后发现每过几天页面就无法正常访问了,而且打开IIS管理器 ...
- Mac Pro 软件收藏
记录下Pro Mac中安装过的软件: 编号 软件名 功能说明 1 QQ 2 微信 3 搜狗输入法 4 Chrome 浏览器 Chrome 及其 插件“个性化设置”备份 5 360云盘 ...
- JS中的prototype(原文地址:http://www.cnblogs.com/yjf512/archive/2011/06/03/2071914.html)
JS中的phototype是JS中比较难理解的一个部分 本文基于下面几个知识点: 1 原型法设计模式 在.Net中可以使用clone()来实现原型法 原型法的主要思想是,现在有1个类A,我想要创建一个 ...
- SDK 移动应用开发系统
AppCan SDK 是一套跨平台移动应用开发系统,基于业内领先的Hybrid App 开发引擎,采用HTML5 标准作为开发语言,支持一次开发多平台适配.AppCan SDK 提供应用向导和界面向导 ...
- excle心得及部分应用案例
目前数据分析方面的知识还学的不多,以后会持续向一些大牛学习,不断的学会做笔记,这样既加深了理解,也能够和大家分享交流.今天就只是把一些excle中常用的知识点总结啦~作为我博客的第一篇吧,希望自己能够 ...