POJ-2492.A Bug's Life(带权并查集)

A Bug‘s Life

Time Limit: 10000MS   Memory Limit: 65536K
Total Submissions: 48043   Accepted: 15483

Description

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.

Input

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.

Output

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.

Sample Input

2
3 3
1 2
2 3
1 3
4 2
1 2
3 4

Sample Output

Scenario #1:
Suspicious bugs found!

Scenario #2:
No suspicious bugs found!

Hint

Huge input,scanf is recommended.

本题大意:给出若干对飞虫的编号表示这一对飞虫进行交配,让你判断这些交配中是否存在有同性恋的可能。

本题思路:使用带路径压缩的并查集,初始状态下初始化所有昆虫相对于它的父亲结点的性别都为0, 将每对昆虫的交配性别逐一加入并查集,加入并查集时需要先进行判断,如果此时两个昆虫父亲结点的编号相等,则判断两个昆虫相对于父亲的性别是否相等,如果相等则已经找到了同性恋标本,不同则跳过这组数据加入下一组数据。如果两个昆虫的父亲节点的标号不同,则将两个昆虫的父亲归并到同一集合中,假设现在是head[ fy] = fx;即将fy的父亲设置为fx,那么我们在合并时要如何才能维持两个集合相对于父亲结点的性别保持正确呢,我们令x相对于fx的性别代号为value [x],fx相对于fy的性别代号为value[fx],y相对于fy的性别代号为value[y],x相对于y为异性则为1,我们可以知道x相对于fy的性别有两条路可以走,一种是value[x] + value[fx], 另一种是value[y] + 1;显然这两者是相等的,因此我们就可以求出转移状态的函数为value[fx] = (value[y] - value[x] + 1) % 2,那么在find函数中我们肯定也是需要调整x相对于fx的性别的,那么要如何调整呢,我们知道,如果x相对于fx的性别为1,fx相对于fy的性别也是1,那么x相对于fy的性别就是0,也就是说我们可以得知x相对于fy的性别等于(value[x] ^ value[fx])。其实我们也可以用位运算判断转移函数,当且仅当x和y相对于其父节点fx和fy的性别相等时fx相对于fy的性别才与x相对于y的性别相同,这样才会满足我们上面谈到的等式。即满足vlaue[fx] = ~(value[x] ^ value[y])。

下面我们给出两种参考代码:

 1 //非位运算
 2 #include <cstdio>
 3 using namespace std;
 4
 5 const int maxn = 2010;
 6
 7 int n, m, flag, tree[maxn], ans[maxn];
 8
 9 void Init() {
10     for(int i = 1; i <= n; i ++) {
11         tree[i] = i;
12         ans[i] = 0;
13     }
14     flag = 1;
15 }
16
17 int find(int x) {
18     if(tree[x] != x) {
19         int t = find(tree[x]);
20         ans[x] = (ans[x] + ans[tree[x]]) % 2;
21         return tree[x] = t;
22     }
23     return x;
24 }
25
26 void TUnion(int x, int y) {
27     int fx = find(x), fy = find(y);
28     if(fx == fy) {
29         if(ans[x] == ans[y]) flag = false;
30     }
31     else {
32         tree[fy] = fx;
33         ans[fy] = (ans[x] + 1 - ans[y]) % 2;
34     }
35 }
36
37 int main () {
38     int a, b, t, i, Case;
39     scanf("%d", &t);
40     for(Case = 1; Case <= t; Case ++) {
41         scanf("%d %d", &n, &m);
42         Init();
43         for(i = 1; i <= m; i ++) {
44             scanf("%d %d", &a, &b);
45             if(flag)
46                 TUnion(a, b);
47         }
48         printf("Scenario #%d:\n",Case);
49         if(flag)
50             printf("No suspicious bugs found!\n\n");
51         else
52             printf("Suspicious bugs found!\n\n");
53     }
54     return 0;
55 }

位运算代替数学等式:

 1 #include <cstdio>
 2 using namespace std;
 3
 4 const int maxn = 2010;
 5
 6 int n, m, flag, tree[maxn], ans[maxn];
 7
 8 void Init() {
 9     for(int i = 1; i <= n; i ++) {
10         tree[i] = i;
11         ans[i] = 0;
12     }
13     flag = 1;
14 }
15
16 int find(int x) {
17     if(tree[x] != x) {
18         int t = find(tree[x]);
19         ans[x] = ans[x] ^ ans[tree[x]];
20         return tree[x] = t;
21     }
22     return x;
23 }
24
25 void TUnion(int x, int y) {
26     int fx = find(x), fy = find(y);
27     if(fx == fy)
28         flag = ans[x] ^ ans[y];
29     else {
30         tree[fx] = fy;
31         ans[fx] = ~(ans[x] ^ ans[y]);
32     }
33 }
34
35 int main () {
36     int a, b, t, i, Case;
37     scanf("%d", &t);
38     for(Case = 1; Case <= t; Case ++) {
39         scanf("%d %d", &n, &m);
40         Init();
41         for(i = 1; i <= m; i ++) {
42             scanf("%d %d", &a, &b);
43             if(flag)
44                 TUnion(a, b);
45         }
46         printf("Scenario #%d:\n",Case);
47         if(flag)
48             printf("No suspicious bugs found!\n\n");
49         else
50             printf("Suspicious bugs found!\n\n");
51     }
52     return 0;
53 }

POJ-2492.A Bug's Life(带权并查集)

原文地址:https://www.cnblogs.com/bianjunting/p/10800985.html

时间: 2024-10-09 07:58:10

POJ-2492.A Bug's Life(带权并查集)的相关文章

POJ 2492 A Bug&#39;s Life (带权并查集 &amp;&amp; 向量偏移)

题意 : 给你 n 只虫且性别只有公母, 接下来给出 m 个关系, 这 m 个关系中都是代表这两只虫能够交配, 就是默认异性, 问你在给出的关系中有没有与异性交配这一事实相反的, 即同性之间给出了交配关系. 分析 : 本题雷同POJ 1182 食物链, 如果会了那一题, 那现在这题便简单多了, 建议先了解食物链的偏移向量做法.这里也是使用向量的思考方式来进行relation的变化, 这里我令 relation = 0为同性, relation = 1为异性, 接下来的步骤就和食物链的雷同了. 优

poj2492A Bug&#39;s Life——带权并查集

题目:http://poj.org/problem?id=2492 所有元素加入同一个并查集中,通过其偏移量%2将其分类为同性与异性,据此判断事件. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; int p,n,m,fa[2005],d[2005]; bool flag; int find(int x) { if(fa[x]==x)return x; el

poj 2492 a bug&#39;s life 简单种类并查集

题意大致为找同性恋的虫子.... 这个比食物链要简单些.思路完全一致,利用取余操作实现关系之间的递推. 个人感觉利用向量,模和投影可能可以实现具有更加复杂关系的并查集. 1 #include<cstdio> 2 using namespace std; 3 const int MAXN=50010; 4 int fa[MAXN]; 5 int rel[MAXN]; // 0代表同类,1代表吃fa[i],2代表被吃 6 void _set(int n) 7 { 8 for(int i=1;i&l

POJ 1984 Navigation Nightmare 二维带权并查集

题目来源:POJ 1984 Navigation Nightmare 题意:给你一颗树 k次询问 求2点之间的曼哈顿距离 并且要在只有开始k条边的情况下 思路:按照方向 我是以左上角为根 左上角为原点 dx[i]为i点距离根的x坐标 dy[]是y坐标 这两个可以通过路径压缩求出 只不过是二维而已 #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int m

【POJ 1984】Navigation Nightmare(带权并查集)

Navigation Nightmare Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usually numbered/labeled 1..N. A series of M (1 <= M < 40,000) vertical and horizontal roads each of varying lengths (1 <= length <= 100

POJ 1984 Navigation Nightmare 【经典带权并查集】

任意门:http://poj.org/problem?id=1984 Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7783   Accepted: 2801 Case Time Limit: 1000MS Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usuall

POJ - 3728:The merchant (Tarjan 带权并查集)

题意:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. 思路:路径压缩,得到每个点到当前根的信息,然后更新即可. 有可以用倍增做. 很久前抄的代码. #include<cstdio> #define min(a,b) (a<b?a:b) #define max(a,b) (a>b?a:b) #define swap(a,b) (a^=b,b^=

poj 1182 食物链 &amp;&amp; nyoj 207(带权并查集)

食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 52414   Accepted: 15346 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同

poj 1733Parity game(map离散+带权并查集)

Parity game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7567   Accepted: 2951 Description Now and then you play the following game with your friend. Your friend writes down a sequence consisting of zeroes and ones. You choose a conti