UVA 11987 Almost Union-Find (单点修改的并查集)
2024-09-04 15:13:54
此题最难处理的操作就是将一个单点改变集合,而普通的并查集是不支持这种操作的。
当结点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+;
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 = ; i <= n; i++) fa[i]=i,fg[i]=false,cnt[i]=,sum[i]=i;
while(m--){
int op,p,q; scanf("%d%d",&op,&p);
if(op!=){
scanf("%d",&q);
int x = Find(p,true), y = Find(q,true);
if(op == ){
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 ;
}
最新文章
- 如何在Chrome下Debug Mocha的测试
- Oracle 11g系列:视图
- 在 Xen 虚拟机下修改系统当前时间
- 非常详细GC学习笔记
- QTableView使用自定义委托(QItemDelegate)
- H面试程序(11): 判断字符串是否包含子串问题
- Login failed for user &#39;NT AUTHORITY\NETWORK SERVICE&#39;的解决方法
- 【DateStructure】 Charnming usages of Map collection in Java
- ASF(传感器)
- dfs算法
- 时间相关库<;ctime>;解析
- python3 第十一章 - 数据类型之str(字符串)
- story 泄露服务器libc版本
- Activity切换的时候生命周期的变化
- Ajax - 汇总
- while循环中出现ssh导致读取文件错误
- [Mac入门]如何在Mac下显示Finder中的所有文件
- 图表ASP:Chart
- No.01——配置编程环境
- jquery.cookie.js $.cookie()是怎么使用
热门文章
- 二十五种网页加速方法和seo优化技巧
- The web.config file for this project is missing the required DirectRequestModule.
- [小工具] C#多线程|匿名委托传参数|测试网站压力--升级版
- WPF语言切换,国际化
- VisualStudio2017中新建的ASP.NET Core项目中的各个文件的含义
- header元素 footer元素 hgroup元素
- Mujin Programming Challenge 2017A - Robot Racing【思维题】
- 洛谷P2867 [USACO06NOV]大广场Big Square
- codevs1105 过河
- 洛谷 P2731 骑马修栅栏 Riding the Fences