POJ1182【种类并查集】
来源:互联网 发布:linux hadoop 下载 编辑:程序博客网 时间:2024/06/05 23:59
思路:
1表示它吃根结点,
2表示它被根结点吃。
判断两个点a, b的关系,我们令p = Find(a), q = Find(b),即p, q分别为a, b子树的根结点。
1. 如果p != q,说明a, b暂时没有关系,那么关于他们的判断都是正确的,然后合并这两个子树。这里是
关键,如何合并两个子树使得合并后的新树能保证正确呢?这里我们规定只能p合并到q(刚才说过了,启发式合并的优化效果并不那么明显,如果我们用启发式合并,就要推出两个式子,
而这个推式子是件比较累的活...所以一般我们都规定一个子树合到另一个子树)。
那么合并后,p的relation肯定要改变,那么改成多少呢?
这里的方法就是找规律,列出部分可能的情况,就差不多能推出式子了。这里式子为:
tree[p].relation = (tree[b].relation - tree[a].relation + 2 + d) % 3; 这里的d为判断语句中a, b的关系。
还有个问题,我们是否需要遍历整个a子树并更新每个结点的状态呢?
答案是不需要的,因为我们可以在Find()函数稍微修改,即结点x继承它的父亲(注意是前父亲,因为路径压缩后父亲就会改变),
即它会继承到p结点的改变,所以我们不需要每个都遍历过去更新。
2. 如果p = q,说明a, b之前已经有关系了。那么我们就判断语句是否是对的,同样找规律推出式子。
即if ( (tree[b].relation + d + 2) % 3 != tree[a].relation ), 那么这句话就是错误的。
3. 再对Find()函数进行些修改,即在路径压缩前纪录前父亲是谁,
直观感觉就是哪个好我咋合并.
---来源百度
1表示它吃根结点,
2表示它被根结点吃。
判断两个点a, b的关系,我们令p = Find(a), q = Find(b),即p, q分别为a, b子树的根结点。
1. 如果p != q,说明a, b暂时没有关系,那么关于他们的判断都是正确的,然后合并这两个子树。这里是
关键,如何合并两个子树使得合并后的新树能保证正确呢?这里我们规定只能p合并到q(刚才说过了,启发式合并的优化效果并不那么明显,如果我们用启发式合并,就要推出两个式子,
而这个推式子是件比较累的活...所以一般我们都规定一个子树合到另一个子树)。
那么合并后,p的relation肯定要改变,那么改成多少呢?
这里的方法就是找规律,列出部分可能的情况,就差不多能推出式子了。这里式子为:
tree[p].relation = (tree[b].relation - tree[a].relation + 2 + d) % 3; 这里的d为判断语句中a, b的关系。
还有个问题,我们是否需要遍历整个a子树并更新每个结点的状态呢?
答案是不需要的,因为我们可以在Find()函数稍微修改,即结点x继承它的父亲(注意是前父亲,因为路径压缩后父亲就会改变),
即它会继承到p结点的改变,所以我们不需要每个都遍历过去更新。
2. 如果p = q,说明a, b之前已经有关系了。那么我们就判断语句是否是对的,同样找规律推出式子。
即if ( (tree[b].relation + d + 2) % 3 != tree[a].relation ), 那么这句话就是错误的。
3. 再对Find()函数进行些修改,即在路径压缩前纪录前父亲是谁,
然后路径压缩后,更新该点的状态(通过继承前父亲的状态,这时候前父亲的状态是已经更新的)。
//#include<bits/stdc++.h>//using namespace std;#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;const int N=5e4+10;int pre[N];int val[N];int n,m,ans;int Find(int x){ if(x==pre[x]) return x; int tmp=pre[x]; pre[x]=Find(tmp); val[x]=(val[x]+val[tmp])%3; return pre[x];}void Merge(int x,int y,int k){ int xx=Find(x); int yy=Find(y); if(xx==yy) { if(k==2&&(val[y]+k+2)%3!=val[x]) ans++; if(k==1&&val[x]!=val[y]) ans++; } else { pre[xx]=yy; val[xx]=(val[y]-val[x]+2+k)%3; }}int main(){int temp,x,y; scanf("%d%d",&n,&m); ans=0; for(int i=1;i<=n;i++) { pre[i]=i; val[i]=0; } while(m--) { scanf("%d%d%d",&temp,&x,&y); if((x>n||y>n)||(temp==2&&x==y)){ ans++; continue; } Merge(x,y,temp); } printf("%d\n",ans);return 0;}然后了解了一下启发式合并,无语。。就是一个智力活。。。
直观感觉就是哪个好我咋合并.
难点就是构造关系(权值):
元素与元素之间关系的转化。
父子结点间关系的转化。
0 0
- poj1182 种类并查集
- poj1182 种类并查集
- POJ1182【种类并查集】
- poj1182食物链(种类并查集)
- poj1182~食物链~种类并查集
- poj1182 食物链 (种类并查集)
- poj2492 poj1182种类并查集
- POJ1182:食物链(种类并查集)
- poj1182食物链 种类并查集
- 【种类并查集】 poj1182食物链
- POJ1182 【NOI2001】 食物链 <种类并查集>
- poj1182 食物链 种类并查集 经典题
- poj1182超详细的种类并查集
- POJ1182食物链,HDU1829(种类并查集)
- POJ1182 食物链 种类并查集(经典)
- 并查集 poj1182
- POJ1182-并查集
- poj1182----并查集
- C实例---文件操作(打开文件)
- JAVA jsoup 架包安装
- 后缀数组模板
- 对象继承训练(2):继承后可以调用父类方法
- .Net程序员学用Oracle系列(11):系统函数(下)
- POJ1182【种类并查集】
- 《程序员自我修养》--动态链接
- 在win7上安装ft232r usb uart 驱动
- Java容器(五):LinkedHashMap实现原理
- IOS网络问题
- Git学习使用(四):远程仓库
- redis源码分析(三)-ziplist的实现
- 1041
- Android(或者Java)通过HttpUrlConnection向SpringMVC请求数据(数据绑定)