UVA 11987 Almost Union-Find (单点修改的并查集)
2015-09-07 22:49
465 查看
此题最难处理的操作就是将一个单点改变集合,而普通的并查集是不支持这种操作的。
当结点p是叶子结点的时候,直接pa[p] = root(q)是可以的,
p没有子结点,这个操作对其它结点不会造成任何影响,
而当p是父结点的时候这种操作会破坏子节点的路径,因此必须保留原来的路径。
我们希望pa[p] = root(q)的同时又保留原来的路径,那么只需要在点上做一个标记,
如果这个点被标记,就沿着新的路径寻找。
此时在修改操作的时候这个点一定是叶子结点,所以可以直接pa[p] = root(q),
而原来的点则变成一个虚点用来保留了原来的路径。
改变集合的操作以及查询都只涉及到单点,这个标记只影响这个点,在二次以及以上的寻找还是要按照原来的路径。
当结点p是叶子结点的时候,直接pa[p] = root(q)是可以的,
p没有子结点,这个操作对其它结点不会造成任何影响,
而当p是父结点的时候这种操作会破坏子节点的路径,因此必须保留原来的路径。
我们希望pa[p] = root(q)的同时又保留原来的路径,那么只需要在点上做一个标记,
如果这个点被标记,就沿着新的路径寻找。
此时在修改操作的时候这个点一定是叶子结点,所以可以直接pa[p] = root(q),
而原来的点则变成一个虚点用来保留了原来的路径。
改变集合的操作以及查询都只涉及到单点,这个标记只影响这个点,在二次以及以上的寻找还是要按照原来的路径。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5+5; int fa[maxn],fa2[maxn],cnt[maxn],sum[maxn]; bool fg[maxn]; int Find(int x,bool d) { if(fg[x]&&d) return Find(fa2[x],false); return x==fa[x]?x:fa[x]=Find(fa[x],false); } int main() { //freopen("in.txt","r",stdin); int n,m; while(~scanf("%d%d",&n,&m)){ for(int i = 1; i <= n; i++) fa[i]=i,fg[i]=false,cnt[i]=1,sum[i]=i; while(m--){ int op,p,q; scanf("%d%d",&op,&p); if(op!=3){ scanf("%d",&q); int x = Find(p,true), y = Find(q,true); if(op == 1){ if(x!=y){ cnt[y] += cnt[x]; sum[y] += sum[x]; fa[x] = y; } }else { if(x!=y){ cnt[x]--,sum[x]-=p; cnt[y]++,sum[y]+=p; fg[p] = true; fa2[p] = y; } } }else { int x = Find(p,true); printf("%d %d\n",cnt[x],sum[x]); } } } return 0; }
相关文章推荐
- 关于那些最好玩的户外APP合集下(适合资深驴友、牛逼设计狮、装逼攻城狮)
- 《机器学习实战》笔记之五——Logistic回归
- MySQL(十六)之使用Mysql-Proxy实现MySQL的读写分离
- react-native试玩(11)-模态
- Codeforces Round #313 (Div. 1) C. Gerald and Giant Chess
- 练习题
- 2015第37周一
- Linux-remote change password (more)
- js整理2
- 转载自伯乐在线
- 主成分分析(PCA)——以2维图像为例
- 【英语】Bingo口语笔记(70) - 最易忽略的2个连读技巧
- [NOIP2010][洛谷P1517] 引水入城|BFS
- 移动应用安全开发指南(Android)--完结篇(http://www.bubuko.com/infodetail-577312.html)
- uva 11294 - Wedding(2 sat)
- android logging 机制及优化
- 制作easyui部门选择插件
- java基础—7.多线程
- ios8绘图方法小记touchesBegan&touchesMoved
- 咏南多层开发框架支持最新的DELPHI 10 SEATTLE