poj 1703 Find them, Catch them (分组并查集 偏移向量实现)
来源:互联网 发布:ubuntu qq2016下载 编辑:程序博客网 时间:2024/05/21 08:45
前段时间做了不少并查集的题目,前天又接触了一种新的类型——分组类型的并查集,通常解法就是加一个偏移量,查了很多资料看了很多的并查集相关的解释终于把向量偏移给搞明白了,不得不说这个“向量偏移的名字”起的真是经典,完全就是借用了向量的思维。一般的分组并查集分组都不是很多(假设为n组),这个时候通常有两中不同的解法:1.开n个并查集,合并一类节点时根据分组信息合并两次,查找的时候也多查一次。2、加个偏移向量数组,在合并和查找时记得要及时的更新偏移量数组。当然第二种方法就高效了很多。
本题正是利用了第二种方法来解,由于只有两组,所以偏移向量只要记录0或者1就可以了,当然这里如果不取余直接记录真实的偏移量也是可以的,但在最后查找判断的时候也少不了取余判断这一步。查找的时候更新偏移量是很好理解的,直接就是向量加然后取余,a->fa(a的根节点时fa),那么在查找的时候,要把a直接连接在fa的父节点上的,这个时候根据向量关系就可以得到offset[a] = offset[a] + offset[fa],这里offset[a]表示从a到其根节点的偏移量,所以在这里查找的之前要先把a的根节点保存下来,因为路径压缩的时候其根节点就变成其新的根节点了。当然因为本题只有两组,所以加个取余就可以了。然后就是合并的时候的更新问题,在合并的的时候本题就是两组即要合并的两点属于不同的组,即如果a在offset为0的组那么b就在offset为1的组,反之亦然,所以他们的偏移量差就是1,那么在合并的时候就要利用向量运算来合并了,假设
a->fa,b->fb(a的根节点是fa,b的根节点是fb),现在要合并a、b,我们再假设把a的父节点合并到b的父节点上也就是pre[fa] = fb;
根据向量运算fa->fb = fa->a + a->b +b->fb,这样就能推导出偏移更新式(2-offset[fa] + 1 + offset[b])%2,化简一下就是(1+offset[b]-offset[a])%2,ok了,这样就解决掉了。
Description
Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds:
1. D [a] [b]
where [a] and [b] are the numbers of two criminals, and they belong to different gangs.
2. A [a] [b]
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang.
Input
Output
Sample Input
15 5A 1 2D 1 2A 1 2D 2 4A 1 4
Sample Output
Not sure yet.In different gangs.In the same gang.
Source
#include <cstdio>#include <cstdlib>const int MAX = 100002;int pre[MAX],offset[MAX];void init(int n){int i;for(i=1;i<=n;++i){pre[i] = i;offset[i] = 0;}}int root(int x){int fx;if(x!=pre[x]){fx = pre[x];pre[x] = root(pre[x]);offset[x] = (offset[x] + offset[fx])%2;}return pre[x];}void merge(int x,int y){int fx = root(x);int fy = root(y);if(fx!=fy){pre[fx] = fy;offset[fx] = (1+offset[y]-offset[x])%2;}}int main(){//freopen("in.txt","r",stdin);int t,n,m,ra,rb;int fa,fb;char com;scanf("%d",&t);while(t--){scanf("%d %d%*c",&n,&m);init(n);while(m--){scanf("%c %d %d%*c",&com,&ra,&rb);if(com=='D'){merge(ra,rb);}else{fa = root(ra);fb = root(rb);if(fa != fb){printf("Not sure yet.\n");continue;}if(offset[ra] != offset[rb]){printf("In different gangs.\n");continue;}printf("In the same gang.\n");}}}return 0;}
- poj 1703 Find them, Catch them (分组并查集 偏移向量实现)
- poj 1703 Find them, Catch them (分组并查集 偏移向量实现)
- POJ 1703 Find them, Catch them(并查集,向量偏移)
- POJ 1703--Find them, Catch them【并查集,向量偏移】
- poj 1703 Find them, Catch them(并查集)
- poj 1703 Find them, Catch them (并查集)
- poj 1703 -- Find them, Catch them(并查集)
- poj 1703 Find them, Catch them(并查集)
- poj 1703 Find them, Catch them (并查集)
- POJ 1703 Find them, Catch them (并查集)
- Find them, Catch them.(POJ-1703)(并查集)
- POJ - 1703 - Find them, Catch them (并查集)
- POJ 1703 Find them, Catch them(并查集)
- poj--1703 Find them, Catch them(并查集)
- POJ 1703 Find them, Catch them (并查集)
- poj 1703 Find them, Catch them(并查集)
- POJ 1703-Find them, Catch them(并查集)
- poj 1703 Find them, Catch them(并查集)
- C++多文件共享全局变量
- 培训的作用-马士兵
- struts2自学学习笔记之一
- 浙大PAT 1010. 一元多项式求导 (解题思路)
- 金币转换
- poj 1703 Find them, Catch them (分组并查集 偏移向量实现)
- 黑马程序员_UDP和TCP简单的通信代码和注释学习笔记
- Java内部类的使用小结
- 整站优化与网页优化的区别
- eclipse只能运行Android程序不能运行java程序
- 凯立德地图版本号/特征码/激活码信息查询方法
- Eclipse常见问题解决方案
- PLSQL 常用 快键设置
- “旱鸭子”交警下水救老人