题意:有N名来自两个帮派的坏蛋,已知一些坏蛋两两不属于同一帮派,求判断给定两个坏蛋是否属于同一帮派。

思路:

解法一: 编号划分

定义并查集为:并查集里的元素i-x表示i属于帮派x,同一个并查集的元素同时成立

可见所有元素个数为2 * N,如果i表示属于帮派A,那么i + N表示属于帮派B,每次输入两个人不在同一帮派的时候,就合并他们分属两个帮派的元素。

#include <iostream>
using namespace std; #define MAX_N 100000 * 2 + 16
int parent[MAX_N];
int height[MAX_N]; void init(const int& n)
{
for (int i = 0; i < n; ++i)
{
parent[i] = i;
height[i] = 0;
}
} int find(const int& x)
{
return parent[x] == x ? x : parent[x] = find(parent[x]);
} void unite(int x, int y)
{
x = find(x);
y = find(y);
if (x == y)return; if (height[x] < height[y])
parent[x] = y;
else
{
parent[y] = x;
if (height[x] == height[y])
++height[x];
}
} bool same(const int& x, const int& y)
{
return find(x) == find(y);
} int main()
{
int T;
cin >> T;
while (T--)
{
int N, M;
cin >> N >> M;
init(N * 2);
char message;
int x, y;
getchar();
while (M--)
{
scanf("%c%d%d", &message, &x, &y);
getchar();
if (message == 'A')
{
if (same(x, y))
{
cout << "In the same gang." << endl;
}
else if (same(x, y + N))
{
cout << "In different gangs." << endl;
}
else
{
cout << "Not sure yet." << endl;
}
}
else
{
unite(x, y + N);
unite(x + N, y);
}
}
}
return 0;
}

解法二:

已知A与B不在一组,B与C不在一组,因为就两组,可得A与C一组。

r[] = 0 表示其根节点属于同一个帮派; r[] = 1表示与其根节点属于不同的帮派。

分析:

开始时初始化自己是自己的父亲 p[x] = x,自己与自己属于同一类 r[x] = 0.
一旦输入 D 断定 x 和 y 属于不同集合后,就连接 x 和 y 所在的树,同时更新 r[]
如果 find(x) 不等于 find(y) 说明还没有判断过 x 与 y 直接输出关系不确定即可
如果 find(x) 等于 find(y),但是他们的r不等,说明属于不同帮派,输出In different gangs.
如果他们的r相等,说明属于同一个帮派,则输出In the same gang
注意:

1.find()函数寻找根节点的时候要不断的更新 r
根据子节点与父亲节点的关系和父节点与爷爷节点的关系,推导子节点与爷爷节点的关系
如果 a 和 b 的关系是 r1, b 和 c 的关系是 r2,
那么 a 和 c 的关系就是(r1 + r2) % 2   //因为只用两种情况所以对 2 取模。

2.Union()联合两棵树的时候也要更新两棵树的根的关系
定义:fx 为 x的根节点, fy 为 y 的根节点
联合时,使得 p[fx] = fy; 同时也要寻找 fx 与 fy 的关系。关系为:(r[x] + r[y] + 1)% 2

#include<cstdio>
const int maxn = 100000 + 10; int p[maxn]; //存父亲节点
int r[maxn]; //存与根节点的关系,0 代表同类, 1代表不同类 int find(int x) //找根节点
{
if (x == p[x]) return x; int t = p[x]; //记录父亲节点 方便下面更新r[]
p[x] = find(p[x]);
r[x] = (r[x] + r[t]) % 2; //根据子节点与父亲节点的关系和父节点与爷爷节点的关系,推导子节点与爷爷节点的关系
return p[x];
} void Union(int x, int y)
{
int fx = find(x);
int fy = find(y); p[fx] = fy;
r[fx] = (r[x] + 1 + r[y]) % 2; //fx与x关系 + x与y的关系 + y与fy的关系 = fx与fy的关系
}
void set(int n)
{
for (int x = 1; x <= n; x++)
{
p[x] = x; //自己是自己的父节点
r[x] = 0; //自己和自己属于同一类
}
} int main()
{
int T;
int n, m;
scanf("%d", &T);
while (T--)
{
scanf("%d%d%*c", &n, &m);
set(n); char c;
int x, y;
while (m--)
{
scanf("%c%d%d%*c", &c, &x, &y); //注意输入
if (c == 'A')
{
if (find(x) == find(y)) //如果根节点相同,则表示能判断关系
{
if (r[x] != r[y]) printf("In different gangs.\n");
else printf("In the same gang.\n");
}
else printf("Not sure yet.\n");
}
else if (c == 'D')
{
Union(x, y);
}
}
}
return 0;
}

POJ 1703 Find them, Catch them (并查集)的更多相关文章

  1. POJ 2236 Wireless Network ||POJ 1703 Find them, Catch them 并查集

    POJ 2236 Wireless Network http://poj.org/problem?id=2236 题目大意: 给你N台损坏的电脑坐标,这些电脑只能与不超过距离d的电脑通信,但如果x和y ...

  2. poj.1703.Find them, Catch them(并查集)

    Find them, Catch them Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I6 ...

  3. POJ 1703 Find them, catch them (并查集)

    题目:Find them,Catch them 刚开始以为是最基本的并查集,无限超时. 这个特殊之处,就是可能有多个集合. 比如输入D 1 2  D 3 4 D 5 6...这就至少有3个集合了.并且 ...

  4. POJ 1703 Find them, Catch them 并查集的应用

    题意:城市中有两个帮派,输入中有情报和询问.情报会告知哪两个人是对立帮派中的人.询问会问具体某两个人的关系. 思路:并查集的应用.首先,将每一个情报中的两人加入并查集,在询问时先判断一下两人是否在一个 ...

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

    手动博客搬家:本文发表于20170805 21:25:49, 原地址https://blog.csdn.net/suncongbo/article/details/76735893 URL: http ...

  6. POJ 1703 Find them, Catch them 并查集,还是有点不理解

    题目不难理解,A判断2人是否属于同一帮派,D确认两人属于不同帮派.于是需要一个数组r[]来判断父亲节点和子节点的关系.具体思路可参考http://blog.csdn.net/freezhanacmor ...

  7. [并查集] POJ 1703 Find them, Catch them

    Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 43132   Accepted: ...

  8. POJ 1703 Find them, Catch them(种类并查集)

    Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 41463   Accepted: ...

  9. 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条臭 ...

  10. POJ 1703 Find them, Catch them (数据结构-并查集)

    Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 31102   Accepted: ...

随机推荐

  1. .net 事务处理

    方法1:直接写入到sql 中在存储过程中使用 BEGIN TRANS, COMMIT TRANS, ROLLBACK TRANS 实现begin transdeclare @orderDetailsE ...

  2. QDialog对话框

    QDialog对话框,用来实现那些只是暂时存在的用户界面,是独立的窗口,但通常也有父窗口对话框有模态和非模态两种,,非模态对话框的行为和使用方法都类似于普通的窗口,模态对话框则有所不同,当模态对话框显 ...

  3. JavaScript之获取表格目标数据(TableDom.getTableData())

    [声明:  1.博文原创 未经同意转载必究,欢迎相互交流] [声明:  2.博主未知情况下转载,需显著处注明博文来源] [声明:  3.谢谢尊重劳动成果,谢谢理解与配合~] 一.背景 在生产过程和生活 ...

  4. Android中实现延时执行操作的几种方法

    1.使用线程的休眠实现延时操作 new Thread() { @Override public void run() { super.run(); Thread.sleep(3000);//休眠3秒 ...

  5. 基于vue-cli的eslint常用设置

    .editorconfig 文件详细备注 # 最顶级的配置,相当于根 editorconfig 直到查找到root=true 才会停止查找不然会一直向上查找 root = true # 通配符 表示匹 ...

  6. CentOS7_JDK安装和环境变量配置

    1.下载 curl -O http://download.Oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.tar.gz 2.改名 mv ...

  7. ORB feature(O for orientation)

    参考链接:http://blog.csdn.net/yang843061497/article/details/38553765 绪论 假如我有2张美女图片,我想确认这2张图片中美女是否是同一个人.这 ...

  8. 在全志平台调试博通的wifi驱动(类似ap6212)【转】

    转自:http://blog.csdn.net/fenzhi1988/article/details/44809779 调试驱动之前,首先先看看驱动代码,了解代码大致工作流程,再根据硬件配置驱动,比如 ...

  9. register 用法注意与深入--【sky原创】

    register 用法注意与深入:   gcc -o test  test.c   这样编译的话会报错的,因为寄存器变量是不能取地址的,只有内存的变量才能取地址 寄存器变量取的是虚拟地址   #inc ...

  10. ES系列九、ES优化聚合查询之深度优先和广度优先

    1.优化聚合查询示例 假设我们现在有一些关于电影的数据集,每条数据里面会有一个数组类型的字段存储表演该电影的所有演员的名字. { "actors" : [ "Fred J ...