【进阶——种类并查集】hdu 1829 A Bug's Life (基础种类并查集)TUD Programming Contest 2005, Darmstadt, Germany
先说说种类并查集吧。
种类并查集是并查集的一种。但是,种类并查集中的数据是分若干类的。具体属于哪一类,有多少类,都要视具体情况而定。当然属于哪一类,要再开一个数组来储存。所以,种类并查集一般有两个数组,一个存并查集内的父子关系,一个存各个节点所属的种类关系。
以这道题为例(题意在后面,如果没有读题,可以先看完题在来看这部分)——
这道题很明显,将bug分成两类,一公一母。但是实际上我们并不关心它是公的还是母的,只关心它们之间是同性还是异性。所以,我们可以设与并查集的根节点同性的为0,反之为1。所以,我们就需要在int mfind(int x)里加上一个对于种类进行的操作。这个操作需要不停地修改每个bug所属的种类。
需要反复修改的理由:每次合并,我们都会将两个集合合并成一个集合,此时就会有一个根节点变成普通节点。那么之前在这个根节点之后的节点所拥有的关系就需要修改。前面已经说了,我们设置的01关系是和根节点相关的关系,那么当根节点变化的时候,我们的对应关系就需要变化。
值得注意的是,这个修改并不需要立刻进行,对于消失的那个根节点上的子节点,只需要在下次查询的时候进行就可以(类似于离线操作。有些人的代码在进行合并之后就进行了一次查找,目的就是马上将查找的节点的种族及时修改,个人认为这是没有必要的)。但是对于消失的那个根节点,我们则需要及时将它与仍然存在的根节点的关系及时修改,因为这里是首次合并时进行的种类关系确定,即,将单个节点合并成一个集合时进行的种类关系确定。
种类关系的确定所使用的运算十分巧妙,我只是大概明白,却还不是完全清楚。种族关系确定时,如果两者的种族相同,那么需要修改其中一方的种族,如果两者的种族不同,那么保持不变。当然,这是这道题的操作,不同的题目会有不同的要求。
题意——
有两种bug,一种是公的,一种是母的。
现在给他们配对,只能公配母,否则就会出bug了,问你他所提出的配对方式有没有bug。
输入——
第一行一个整数t,表示有t组数据。
接下来,每组数据第一行有两个整数n, m,表示共有n个虫子,m种配对。
接下来m行,每行两个整数a, b,表示一种配对。
输出——
输出是第几组数据
输出是否存在bug。
数据举例——
1
3 3
1 2
1 3
2 3
这里表示共有1组数据,这组数据包含3只bug和3种配对。
由于1可以与2配,1可以与3配,那么2, 3同性……所以这一组是个bug(这里不存在gay和百合……)
上代码——
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std; const int M = ; int fm[M];
int n, m, t;
bool tp[M], flag; //tp[]记录种族,flag记录是否存在bug int mfind(int x) //查询操作
{
if(fm[x] == x) return x;
int fx = fm[x];
fm[x] = mfind(fm[x]);
tp[x] = tp[fx]^tp[x]; //修改种族,对查询的子节点进行
return fm[x];
} void mmerge(int x, int y)
{
int fx = mfind(x);
int fy = mfind(y);
//printf("%5d%5d\n", fx, fy);
if(fx != fy) //合并操作
{
fm[fy] = fx;
tp[fy] = tp[x]^tp[y]^; //修改种族,对消失的根节点进行
}
else if(tp[x] == tp[y]) flag = ; //如果两个节点属于同一并查集且种族相同,则出现bug
} void init() //各种数据初始化
{
memset(tp, , sizeof(tp)); //种类初始化,所有节点都和自己属于同一种类
flag = ; //目前没有bug
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) fm[i] = i; //并查集初始化,这个不用多说了吧
} void work()
{
for(int i = ; i < m; i++)
{
int a, b;
scanf("%d%d", &a, &b);
if(!flag) mmerge(a, b); //不存在bug才进行并查集操作,
}
} void output(int tm)
{
printf("Scenario #%d:\n", tm);
if(!flag) printf("No suspicious bugs found!\n");
else printf("Suspicious bugs found!\n");
//for(int i = 1; i <= n; i++) printf("%5d", tp[i]);
//printf("\n");
printf("\n");
} int main()
{
//freopen("test.in", "r", stdin);
scanf("%d", &t);
for(int tm = ; tm <= t; tm++)
{
init();
work();
output(tm);
}
return ;
}
当然,这个代码里我使用的是抑或^符号来处理的,主要原因是这里一共只有两个种类(使用bool数组进行记录也是如此的原因),如果种类比较多,就需要使用%符号或者其他的方式处理了。
ps:我也是一边写博客一边思考的,在写完的时候对于这个算法的思路确实又清晰了不少,看来写博客还是很有用处的。
【进阶——种类并查集】hdu 1829 A Bug's Life (基础种类并查集)TUD Programming Contest 2005, Darmstadt, Germany的更多相关文章
- HDU 1829 A Bug's Life (种类并查集)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1829 A Bug's Life Time Limit: 15000/5000 MS (Java/Oth ...
- hdu 1829 A Bug's Life(分组并查集(偏移量))
A Bug's Life Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- HDU 1829 A Bug's Life(种类并查集)
思路:见代码吧. #include <stdio.h> #include <string.h> #include <set> #include <vector ...
- hdu 1182 A Bug's Life(简单种类并查集)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1829 题意:就是给你m条关系a与b有性关系,问这些关系中是否有同性恋 这是一道简单的种类并查集,而且也 ...
- hdu - 1829 A Bug's Life (并查集)&&poj - 2492 A Bug's Life && poj 1703 Find them, Catch them
http://acm.hdu.edu.cn/showproblem.php?pid=1829 http://poj.org/problem?id=2492 臭虫有两种性别,并且只有异性相吸,给定n条臭 ...
- hdu 1829 A Bug's Life(并查集)
A Bu ...
- HDU 1829 A Bug's Life 【带权并查集/补集法/向量法】
Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes ...
- hdu1829&&poj2492 A Bug's Life 基础种类并查集
把性别相同的虫子放在同一个集合,然后每读入一对虫子号,判断它们在不在同一集合,在则同性别,不在则继续 #include <cstdio> #include <cstring> ...
- hdu1829 A Bug's Life 基础种类并查集
题目的大意可以理解为:A爱B,B爱C ……给出一系列爱恋的关系,推断有没有同性恋. 思路是把相同性别的归为一个集合(等价类),异性的异性为同性. #include<iostream> #i ...
随机推荐
- 深入浅出Java并发包—锁机制(三)
接上文<深入浅出Java并发包—锁机制(二)> 由锁衍生的下一个对象是条件变量,这个对象的存在很大程度上是为了解决Object.wait/notify/notifyAll难以使用的问题. ...
- Java实现二维码QRCode的编码和解码
涉及到的一些主要类库,方便大家下载: 编码lib:Qrcode_swetake.jar (官网介绍-- http://www.swetake.com/qr/index-e.html) 解码lib: ...
- lintcode:落单的数
题目: 落单的数 给出2*n + 1 个的数字,除其中一个数字之外其他每个数字均出现两次,找到这个数字. 样例 给出 [1,2,2,1,3,4,3],返回 4 挑战 一次遍历,常数级的额外空间复杂度 ...
- map的详细用法
map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时 ...
- MD5加密算法测试
在用户注册这一块,密码加密保证客户信息安全是最重要的,在网上查询了一些资料,发现加密算法比较流行的有MD5,DES和SHA. 虽然SHA与MD5通过碰撞法被破解了,但是MD5和SHA仍被公认是安全的加 ...
- Nim语言:Pascal的语法,Python的缩进
http://nim-lang.org/ 德国人Andreas Rumpf的作品,原因是他对过去使用的每种语言都不满意(Pascal也不满意?).以前叫Nimrod语言,从0.96版本开始改名为Nim ...
- AO创建IFeature的两种方法
原文地址:http://www.cnblogs.com/MyLucifer/archive/2010/12/01/1893212.html 在ArcGIS Resouce Center中,ESRI介绍 ...
- Android列表视图(List View)
Android列表视图(ListView) ListView是一个显示滚动项列表的示视图组(viewgroup),通过使用适配器(Adapter)把这些列表项自动插入到列表中.适配器比如从一个数组或是 ...
- C++ string类的学习
string类对于处理字符串的一些应用非常的方便,我个人感觉,string和字符数组const char *很像,而且又比字符数组用起来方便的多. 注意其删除,取子串,插入等函数里面都有一个重载版本是 ...
- 数据库MySQL-Oracle-DB2-SQLServer分页查询
1. MySQL分页查询 (1)关键字: LIMIT beginIndex, maxRow (2)示例: LIMIT子句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数. 如果给出 ...