一个多月前的题目了。数算实习的作业有三个题,食物链,冰阔落和这一道。
冰阔落是模板题就不写了,食物链拼死拼活过不了。这个题参考了标程之后知道怎么回事了就写写。

题目:

描述
Background
Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only interact with bugs of the opposite gender. In his experiment, individual bugs and their interactions were easy to identify, because numbers were printed on their backs.
Problem
Given a list of bug interactions, decide whether the experiment supports his assumption of two genders with no homosexual bugs or if it contains some bug interactions that falsify it.
输入
The first line of the input contains the number of scenarios. Each scenario starts with one line giving the number of bugs (at least one, and up to 2000) and the number of interactions (up to 1000000) separated by a single space. In the following lines, each interaction is given in the form of two distinct bug numbers separated by a single space. Bugs are numbered consecutively starting from one.
输出
The output for every scenario is a line containing “Scenario #i:”, where i is the number of the scenario starting at 1, followed by one line saying either “No suspicious bugs found!” if the experiment is consistent with his assumption about the bugs’ sexual behavior, or “Suspicious bugs found!” if Professor Hopper’s assumption is definitely wrong.
样例输入
2
3 3
1 2
2 3
1 3
4 2
1 2
3 4
样例输出
Scenario #1:
Suspicious bugs found!

Scenario #2:
No suspicious bugs found!

大概就是说一个博士在研究昆虫的性别行为,只有性别不同的虫子才会在一起,现在统计了所有在一起的虫子对,问博士的猜想是否正确。
最近数算课也讲了并查集,并查集的主要操作就是合并(两个集合)和查找(两个元素是否在一个集合中)。并查集实际上是一个森林,一个集合对应一棵树,合并就是把一棵树的根挂在另一棵树的某个节点下面,查找就是看两个元素是否在同一棵树上。同时注意到,如果树的层数太多而且不平衡(借用二叉树的概念),那么时间复杂度会很高,甚至到O(N),而这是不能接受的。因此产生了路径压缩算法,就是在递归寻找这个元素所属树的根的时候,每一次都把这个元素往上挂一层,多次操作之后这棵树的深度很可能就是2,这样查找就是O(1)的了。
数算的角度就是并查集实际上用来求解等价类的问题,合并实际上是利用了等价关系的传递性。查找就是找这个元素到底在哪个等价类里面。这样可能理解起来更加方便一点。
回到题目,问题是:把什么设置成等价关系?容易想到把性别相同的虫子归为等价,但是显然这样无法操作。之后的思路就是,把性别是否已知这个归为一类,其中一个虫子设置成基准性别,也就是树的根,其他虫子和这个虫子的性别比较,相同为1,不同为0。等价性:一个虫子与他自己的性别关系已知;虫子x和y之间的关系已知,则y与x之间的关系已知;若x与y之间的关系已知,y与z之间的关系已知,则x与z之间的关系已知。
具体实现就是最初设置parent数组,每个虫子都是一棵单独的树。同时设置gender[x][y],表示虫子x和y之间的关系。若性别相同,设置成1,性别不同,设置成0.每次输入interaction的时候比较这俩虫子的根。若根相同,与根的性别关系相同,则假设不成立,否则继续;若根不同,则默认这俩虫子性别不同,然后若这俩虫子和根的性别关系不同,则得出根之间的性别关系相同,若和根的性别关系相同,则根之间的性别关系不同。则把这两个树合并。
下面的问题就是如何得知虫子与根之间的关系。这就是路径压缩函数的变形。利用传递性。虫子和根的关系 = !(虫子与父亲的关系^父亲和根的关系)。
值得注意的是,一个是gender要设置成二维,这个应该挺显然的,但是我在写这个博客的时候居然一开始想当然地认为一维数组就行了。第二个是不要太多分类讨论,尽量运用简洁的算式。比如gender[x][z] = !(gender[x][y] ^ gender[y][z])(其实把性别相同设置成0,性别不同设置成1会更简洁,但是懒得改了)
下面是AC代码:

#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn = 2005;
int parent[maxn];
int gender[maxn][maxn];
int getroot(int a)
{if (parent[a] != a) {int t = parent[a];parent[a] = getroot(parent[a]);gender[a][parent[a]] = gender[parent[a]][a] = !(gender[a][t] ^ gender[t][parent[a]]);}return parent[a];
}
int main()
{int n;scanf("%d", &n);for (int i = 0; i < n; ++i){int actnum, bugnum;scanf("%d%d", &bugnum, &actnum);memset(parent, 0, sizeof(parent));memset(gender, -1, sizeof(gender));for (int j = 0; j <bugnum; ++j){gender[j+1][j+1] = 1;parent[j+1] = j+1;}int a, b;int flag = 1;for (int j = 0; j <actnum; ++j){scanf("%d%d", &a, &b);int pa = getroot(a);int pb = getroot(b);if (pa == pb){if (!(gender[a][pa] ^ gender[b][pb])){flag=false;}}else {//如果根不同,那么gender[pa][pb]一定为-1gender[pa][pb] = gender[pa][a] ^ gender[pb][b];parent[pa] = pb;}}printf("Scenario #%d:\n%suspicious bugs found!\n\n", i+1, flag? "No s": "S");}return 0;}

突然发现poj貌似比hdu严格,我写博客的时候作业已经结束了我就去vjudge上提交,结果bugnum和actnum写反了hdu居然都能过……

并查集:A bug's life相关推荐

  1. A Bug‘s Life POJ 2492 加权并查集

    A Bug's Life POJ 2492 加权并查集 传送门:http://poj.org/problem?id=2492 Description Background Professor Hopp ...

  2. poj 2492A Bug's Life(并查集)

    /* 目大意:输入一个数t,表示测试组数.然后每组第一行两个数字n,m,n表示有n只昆虫,编号从1-n,m表示下面要输入m行交配情况,每行两个整数,表示这两个编号的昆虫为异性,要交配. 要求统计交配过 ...

  3. 【分组并查集讲解】A Bug‘s Life(例题)

    举例: 我们开一个两倍大小的并查集.例如,假如我们要维护4个元素的并查集,我们改为开8个单位的空间: 我们用14维护朋友关系(就这道题而言,是指关在同一个监狱的狱友),用58维护敌人关系(这道题里是指 ...

  4. POJ 2492 A Bug's Life 带权并查集

    题意: 思路: mod2 意义下的带权并查集 如果两只虫子是异性恋,它们的距离应该是1. 如果两只虫子相恋且距离为零,则它们是同性恋. (出题人好猥琐啊) 注意: 不能输入一半就break出来.... ...

  5. POJ-2492-A Bug's Life [并查集]

    题目传送门 题意: 每行两个数字,表示两个虫子相互喜欢,只有异性才能相互喜欢,所以求里面有没有基佬或者拉拉= =. 思路: 种类并查集,只有两种状态,父节点与自身性别相同,父节点与自身性别不同. 更新 ...

  6. BZOJ 2303 方格染色(带权并查集)

    要使得每个2*2的矩形有奇数个红色,如果我们把红色记为1,蓝色记为0,那么我们得到了这2*2的矩形里的数字异或和为1. 对于每个方格则有a(i,j)^a(i-1,j)^a(i,j-1)^a(i-1,j ...

  7. 洛谷 - P1111 - 修复公路 - 并查集

    https://www.luogu.org/problemnew/solution/P1111 并查集的水题,水题都错了好多发. 首先并不是有环就退出,而是连通分支为1才退出,每次合并成功连通分支才会 ...

  8. POJ 1703 Find them, Catch them(并查集高级应用)

    POJ 1703 Find them, Catch them(并查集高级应用) 手动博客搬家:本文发表于20170805 21:25:49, 原地址https://blog.csdn.net/sunc ...

  9. 【蓝桥杯官网试题 - 历届试题】发现环(dfs+并查集,或无向图tarjan判环,无向环,或拓扑排序)

    题干: 问题描述 小明的实验室有N台电脑,编号1~N.原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络.在树形网络上,任意两台电脑之间有唯一的路径相连. 不过在最近一次维护网络时,管理员 ...

  10. 树形结构 —— 并查集

    [概述] 并查集(Union-Find Set)是一种用于分离集合操作的抽象数据类型,其处理的是集合(set)之间的关系,一般处理的是图的连通分量,当给出两个的元素的一个无序对 (a,b) 时,需要快 ...

最新文章

  1. SharePoint 2013 APP 开发示例 (六)服务端跨域访问 Web Service (REST API)
  2. linux GPIO驱动详解
  3. mysql 里面不等于符号_mysql 不等于 符号写法
  4. drill apache_Apache Drill:如何创建新功能?
  5. USACO3.15stamps(dp)
  6. 体验paddle2.0rc版本API-Model--实现Mnist数据集模型训练
  7. restTemplate配置及使用
  8. nltk packages下载问题
  9. 关于对于工作方式的一些总结。
  10. 使用docker优雅的部署你的nuxtjs项目
  11. Mybatis原理解析(三)--getMapper动态获取接口实现类
  12. STM32/STM8选型手册
  13. free源码分析---1
  14. MFC Ribbon模式下 菜单promt鼠标滑过时候的提示是需要在属性的promt前面加上\n
  15. RecyclerView clipToPadding
  16. 一个口 光纤 两条线 交换机 上 光纤 两条线 双纤 单纤 尾纤 分光器 双纤 双纤转单纤 接 分光器
  17. pr制作马赛克的效果,动态光效素材应用,
  18. [附源码]java毕业设计网上拍卖系统
  19. 密码爆破工具:Medusa(美杜莎)-操作说明hydra-操作说明
  20. mysql unix_timestamp now() dfdfd f_数据库函数lpad的搜索结果-阿里云开发者社区

热门文章

  1. matlab去除图片水印_一种基于MATLAB去图片水印方法
  2. hausaufgabe--python 22- Recurse
  3. Servlet 身份验证体系结构
  4. 小微个人网站如何接入免费短信验证码
  5. edge打开pdf不显示印章_edge打开pdf后,draw功能栏怎么没了?
  6. P、NP、NPC、NP-Hard
  7. java罗马数字_整数转罗马数字以及罗马数字转整数(java实现)
  8. PTA数据结构-01-复杂度1 最大子列和问题
  9. python声音模拟_5秒钟让python克隆别人的声音
  10. 克隆你的声音,可能只需要5秒钟:MockingBird实现AI拟声 (详解)