【POJ No. 1703】 帮派 Find them, Catch them

POJ 题目地址

【题意】

警察局决定从两个帮派青龙帮和白蛇帮开始治理混乱,首先需要确定犯罪分子属于哪个团伙。比如,有两名罪犯,他们是否属于同一帮派?

警察必须根据不完整的信息做出判断,因为歹徒总是暗中行动的。假设有N (N ≤10^5 )个罪犯,编号为1~N,其中至少有一人属于青龙帮,至少有一人属于白蛇帮,请依次给出M(M ≤10^5 )个消息,消息类型有两种:D a b ,表示a 和b 属于不同的帮派;A a b ,表示查询a 和b 是否属于同一帮派。

【输入输出】

输入:

第1行包含单个整数T (1≤T ≤20),即测试用例的数量。每个测试用例都以两个整数N 和M 开始;接着是M 行,每行都包含如上所述的一个消息。

输出:

对每一个查询操作,都根据之前获得的信息进行判断,答案可能是In the same gangs、In the different gangs和Not sureyet,分别表示在同一帮派中、在不同的帮派中和还不确定。

【样例】

【思路分析】

可以用一个集合表示一个帮派,根据集合号判定是否属于同一帮派。在并查集的基本操作中,Union(x , y )表示将x 、y 合并为同一个集合。

与并查集的集合合并不同,本题要求将两者划分为不同的集合,该怎么办呢?

① 划分为不同集合的方法:可以给每个节点x 都复制一个影子x+n ,将x、y 划分为不同的集合,只需将x 和y 的影子(y +n )合并为同一集合,并将x 的影子(x +n )和y 合并为同一集合。执行Union(x , y +n )、Union(x +n , y ),表示x 、y 属于不同的集合。

② 判定是否属于同一集合:因为将x、y 划分为不同的集合时,与彼此的影子进行了合并,即x 和y 的影子(y +n )集合号相等或者x的影子(x +n )和y 集合号相等时,说明x、y 属于不同的集合;而x和y 集合号相等或者x 的影子(x +n )和y 的影子(y +n )集合号相等时,说明x、y 属于同一集合;对于其他情况,不确定其是否属于同一集合。

③ 合并优化:若将高树合并到矮树之下,则合并后的树高增1;若将矮树合并到高树之下,则合并后的树高不变。树高越大,查找祖宗时经过的节点越多,效率越低。因此采用启发式合并,将矮树合并到高树之下,若树的高度一样,则合并后树根的高度增1。

【算法设计】

① 初始化。将n 扩大为2n 个节点,初始化每个节点的集合号都为其自身,高度为0。

② 划分为不同的集合。执行Union(x , y +n )、Union(x +n ,y ),表示x 、y 属于不同的集合。

③ 判定是否属于同一集合。若(Find(y +n )==Find(x)||Find(x +n )==Find(y )),则属于不同的集合;若(Find(x)==Find(y )||Find(x +n )==Find(y +n )),则属于同一集合;否则不确定是否属于同一集合。

【举个例子】

根据输入样例,求解过程如下。

① 初始化。根据样例,一共有5个节点,将其扩大为10个节点。初始化每个节点的集合号都为其自身,高度h 为0。

② A 1 2:查询1和2是否属于同一帮派。Find(1)=1,Find(6)=6,Find(2)=2,Find(7)=7,前两个判定条件均不满足,不确定1和2是否属于同一帮派。

③ D 1 2:将1和2划分为不同的集合。将1和2+5合并,将1+5和2合并。

⑤ A 1 2:查询1和2是否属于同一帮派。因为(Find(2+5)==Find(1)||Find(1+5)==Find(2)),所以1和2不属于同一帮派。

⑤ D 2 4:将2和4划分为不同的集合。可以将2和4+5合并,将2+5和4合并。将高度小的树合并到高度大的树下面,因此将9合并到2下面,将4合并到7下面。

⑥ A 1 4:表示查询1和4是否属于同一帮派。因为(Find(1)==Find(4)||Find(1+5)==Find(4+5)),所以1和4属于同一帮派。

【算法实现】

#include<cstdio>
#include<cstring>const int MAXN=200010;//因为有影子数据量*2,不然会越界
using namespace std;
int n,m;
int fa[MAXN],h[MAXN]; //h用来区分树的高度,但其不存储树的具体高度void Init(){ //初始化。初始化每个节点的集合号为其自身,高度为0。for(int i=1;i<=2*n;i++){fa[i]=i;h[i]=0;}
}int Find(int x){ //查找集合号。与在并查集中查找集合号的方法一样。if(x!=fa[x])fa[x]=Find(fa[x]); return fa[x];
}//划分为不同的集合。将x、y 划分为不同的集合,分为两个步
//骤:①Union(x , y +n ),②Union (x +n , y )。Union()操作与并查
//集的合并方法一致,这里只是做了合并优化,把矮树合并到高树之下,
//若树的高度一样,则合并后树根的高度增1。void Union(int x,int y){int a=Find(x);int b=Find(y);if(a==b) return;if(h[a]>h[b]) //启发式合并,把矮树合并到高树之下fa[b]=a;else{fa[a]=b;if(h[a]==h[b])//若树的高度一样,合并后树根的树高+1h[b]++;}
}int main(){int T;scanf("%d", &T);//  判定结果。若划分不同的集合,则执行Union(x , y +n )、
//Union(x +n , y )。若判定结果,则根据3个判定条件输出答案即可。while(T--){scanf("%d%d",&n,&m);Init();while(m--){char ch[2];int x,y;scanf("%s%d%d",ch,&x,&y);if(ch[0]=='D'){Union(x,y+n);Union(x+n,y);}else{if(Find(y+n)==Find(x)||Find(x+n)==Find(y))printf("In different gangs.\n");else if(Find(x)==Find(y)||Find(x+n)==Find(y+n))printf("In the same gang.\n");elseprintf("Not sure yet.\n");}}}return 0;
}

【POJ No. 1703】 帮派 Find them, Catch them相关推荐

  1. 【POJ - 1703】Find them, Catch them(带权并查集之--种类并查集 权为与父节点关系)

    题干: Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 36176   Accep ...

  2. poj 3278 bzoj 1646: [Usaco2007 Open]Catch That Cow 抓住那只牛(BFS)

    1646: [Usaco2007 Open]Catch That Cow 抓住那只牛 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1223  Solv ...

  3. POJ前面的题目算法思路【转】

    1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 85% 2005-5-7 1002 487-3279 n/a 90% 2005-5- ...

  4. POJ 1703 Find them, Catch them(路径压缩并查集)

    POJ 1703 Find them, Catch them(路径压缩并查集) 2014年03月11日 20:13:54 阅读数:881 POJ 1703 Find them, Catch them( ...

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

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

  6. (并查集 带关系)Find them, Catch them -- poj -- 1703

    链接: http://poj.org/problem?id=1703 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3676 ...

  7. POJ 1703 Find them, Catch them【并查集】

    题意: 有 N 个人分属于两个帮派,对应两种操作: A   X Y      询问x,y 是否属于一个帮派,或两者关系不能确定. D   X Y      X和Y 分属不同帮派 分析: 感觉就是简化版 ...

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

    题意: 在这个城市里有两个黑帮团伙,现在给出N个人,问任意两个人他们是否在同一个团伙 1.输入D x y代表x于y不在一个团伙里 2.输入A x y要输出x与y是否在同一团伙或者不确定他们在同一个团伙 ...

  9. POJ 1703 Find them, Catch them 并查集

    题意:给你t组数据,每组数据给你编号为1-n的坏人,这些坏人要么属于团伙A,要么属于团伙B,然后给你m次操作: A操作:询问x和y是不是同一个团伙 D操作:告诉你x和y不是同一个团伙 思路:和POJ ...

最新文章

  1. android 弹出一个在桌面上出现的window
  2. 以下不是python文件读写方法的是-Python 文件I/O
  3. Set Matrix Zeroes
  4. LiveVideoStack线上分享第三季(八):移动视频工厂 - 如何实现“快速、灵活、简单的视频剪辑框架...
  5. VScode配置ESlint自动修复格式化
  6. 测试基础理论知识(二)
  7. Java与Python:哪一个最适合您? [信息图]
  8. Oracle 扼杀 Java EE!
  9. Linux下SVN 命令操作手册
  10. Apache 服务器端安装配置(Windows版本)
  11. java异常中的finally(一)
  12. MOS管防倒灌电路设计及其过程分析
  13. oppo锁屏断网设置在哪里呀_oppo锁屏时钟怎么改格式?锁屏时钟位置在哪里设置调整...
  14. java汉字拼音简码_java生成首字母拼音简码的总结
  15. 【论文解读】 FPGA实现卷积神经网络CNN(二): Optimizing FPGA-based Accelerator Design for DCNN
  16. “好好活着,别生气,余生很贵!”
  17. 记一次失败的机械键盘拆机换轴经历(含失败的经验总结)
  18. java毕业设计图书借阅管理系统mybatis+源码+调试部署+系统+数据库+lw
  19. c# contains方法_C# 基础知识系列- 3 集合数组
  20. java中遍历一个对象的所有属性

热门文章

  1. rtklib三之relpos rtkpo庖丁解牛
  2. 算法DFS之水管问题
  3. 春运车票还没抢 钱就被骗走了 这些诈骗手段你得留个心
  4. 《统计学》——思考题第八章假设检验(贾俊平)
  5. IOS开发之----资源汇总
  6. angularjs html 支付宝支付,angular仿支付宝密码框输入效果
  7. K3cloud物料保存校验增加:使用组织+物料名称+规格型号+物料属性的校验
  8. Qin Shi Huang's National Road System
  9. fully qualified name
  10. three.js 楼层加载动画