写这篇博客也是为了方便自己以后能够快速回顾LCT,再探索其其他的用途

以后回顾LCT可以参考这篇博客:写得很清楚

题目如下

Rose would like to find whether they truly love each other.

Rose lets Jack draw a graph of N vertices, and Rose herself writes a set of vertex pair (u​i​​,v​i​​), named S.

Initially the graph has no edge and S is empty.

There are Q operations of 5 kinds, which are listed below:

1.Jack adds edge (u,v) into the graph. It is guaranteed that u and v are unreachable before adding.

2.Jack deletes edge (u,v) from the graph. It is guaranteed that this edge exists before deleting.

3.Rose adds vertex pair (u,v) into S. It is guaranteed that (u,v) is not in S before adding.

4.Rose deletes vertex pair (u,v) from S. It is guaranteed that (u,v) exists before deleting.

5.Ask if they love each other, that is, whether every vertex pair in S is reachable in the graph. In other words, whether for every vertex pair (u,v) in S, u and v are reachable in the graph.

Input
The first line contains an integer T (1≤T≤100) — the number of test cases.

The first line of each test case contains two integers N (3≤N≤100000), Q (3≤Q≤300000) — the number of vertices, the number of operations.

The next Q lines describe the operations, where the i-th line contains three integers Type, u, v (u<v) for the first four operations and one integer Type for the last (fifth) kind of operation.

It is guaranteed that ∑N≤300000 and ∑Q≤500000.

Output
For each operation of the fifth kind, output “YES” or “NO” in one line to indicate the answer, with the same order as the input.

Sample Input
1
5 10
5
3 2 5
4 2 5
1 4 5
2 4 5
5
1 1 2
3 1 5
4 1 5
2 1 2

Sample Output
YES
YES
可以发现题目中的操作涉及删边,加边,存在多个连通块,更重要的是,由于每次加边保证两个点不连通所以所有连通块都满足树的形态。所以我们很快就想到可能可以用到LCT来解决这个问题

判断所有点对是否都联通有个巧妙的方法:每次添加一个点对(u,v)到集合S中时, 将这组点对随机一个值Value,可以用二维map存,并且将这两个点的权值都异或上Value,这样如果一个连通块内所有点的抑或和为0,即连通块内部包含的都是S中完整的点对。如果每个连通块的抑或和都为0,那么S中所有的点对都联通。

对于前四个操作,只要维护连通块的抑或和即可,同时维护一共有多少个连通块抑或和不为零

这里涉及到LCT维护子树信息的操作(当然这题只要维护整颗树的信息)对于点x,用一个sum[x]维护子树抑或和(包括x),other[x]维护x所有虚边连接的点的抑或和(不包括x),这样不光对本题,对于查询子树信息的题,例如要查询y的子树信息,只需要access(y),other[y]中便记录了所有子树信息(不包括y),就成功了

可惜我的代码习惯不好,还是显得很冗长,不过懒得改了<_>


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <map> using namespace std;const int Maxn = 100010;int ch[Maxn][2], fa[Maxn], rev[Maxn], Sum[Maxn], Cnt, Val[Maxn], Other[Maxn];bool isroot(int x){return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}void pushup(int h){Sum[h] = Val[h];Sum[h] ^= Other[h];if (ch[h][0]) Sum[h] ^= Sum[ch[h][0]];if (ch[h][1]) Sum[h] ^= Sum[ch[h][1]];
}void pushdown(int h){if(!rev[h]) return;rev[h] = 0;swap(ch[h][0], ch[h][1]);if(ch[h][0]) rev[ch[h][0]] ^= 1;if(ch[h][1]) rev[ch[h][1]] ^= 1;
}void PUSHDOWN(int h){if(!isroot(h)) PUSHDOWN(fa[h]);pushdown(h);
}void rotate(int h){int father = fa[h], grandfa = fa[father];bool w = (ch[father][1] == h);fa[ch[h][w^1]] = father;ch[father][w] = ch[h][w^1];fa[father] = h;ch[h][w^1] = father;fa[h] = grandfa;if(ch[grandfa][0] == father) ch[grandfa][0] = h;else if(ch[grandfa][1] == father) ch[grandfa][1] = h;pushup(father), pushup(h);
}bool pd (int x) {return ch[fa[x]][0] == x;}void splay (int h) {PUSHDOWN(h);while (!isroot(h)) {if(!isroot(fa[h]) && pd(fa[h]) == pd(h)) rotate(fa[h]);rotate(h);}
}void access(int h){int y = 0;while (h) {splay(h);Other[h] ^= Sum[ch[h][1]];//维护子树信息只需要在access和link操作多添几句Other[h] ^= Sum[y];ch[h][1] = y;pushup(h);y = h;h = fa[h];}
}void makeroot (int h) {access(h);splay(h);pushup(h);rev[h] ^= 1;
}int findroot (int x) {access(x);splay(x);while(ch[x][0])   x = ch[x][0];return x;
}void link (int x,int y) {makeroot(x);makeroot(y);int Pre = (Sum[x] != 0) + (Sum[y] != 0);fa[x] = y;Other[y] ^= Sum[x];pushup(y);int Next = (Sum[y] != 0);Cnt += Next - Pre;//用变化后的数量减去变化前的数量,下面几个一样的地方同理
}void cut (int x,int y) {makeroot(x);int Pre = (Sum[x] != 0);access(y);splay(y);fa[x] = ch[y][0] = 0;pushup(y);int Next = (Sum[x] != 0) + (Sum[y] != 0);Cnt += Next - Pre;
}map<int, map<int, int> > q;void Init(int N) {q.clear();Cnt = 0;for (int i = 1; i <= N; ++i) Val[i] = Sum[i] = fa[i] = ch[i][0] = ch[i][1] = Other[i] = 0;
}void Add(int x, int Value) {int Pre = (Sum[x] != 0);Val[x] ^= Value; pushup(x);int Next = (Sum[x] != 0);Cnt += Next - Pre;
}int main() {srand(time(NULL));int T;scanf ("%d", &T);while (T--) {int N, Q;scanf ("%d%d", &N, &Q);Init(N);while (Q--) {int th;scanf ("%d", &th);int x, y;if (th != 5) scanf ("%d%d", &x, &y);if (th == 1) {link(x, y);}else if (th == 2) {cut (x, y);}else if (th == 3) {int Value = rand();q[x][y] = q[y][x] = Value;makeroot(x);Add(x, Value); makeroot(y);Add(y, Value);}else if (th == 4) {int Value = q[x][y];q[x][y] = q[y][x] = 0;makeroot(x);Add(x, Value);makeroot(y);Add(y, Value);}else {if (Cnt) printf ("NO\n");else printf ("YES\n");}}}return 0;
}

仰天大笑出门去,我辈岂是蓬蒿人!

2019-ICPC沈阳J题Graph相关推荐

  1. 2019 ICPC 沈阳

    2019 ICPC 沈阳 F(签到) 图中找度数为1的点 #include<iostream> #include<cstdio> #include<cstring> ...

  2. 2019 ICPC NAC补题

    题目链接(PDF):https://cs.baylor.edu/~hamerly/icpc/qualifier_2019/naq2019.pdf A Circuit Math 题解:后缀表达式,从左到 ...

  3. 2021 ICPC沈阳 J.Luggage Lock(bfs,模拟)

    题目描述 题目链接 题目分析 这是一道很明显的bfs+模拟的题(和八数码是一类题)这是一道很明显的bfs+模拟的题(和八数码是一类题)这是一道很明显的bfs+模拟的题(和八数码是一类题) 因为起点和终 ...

  4. 2019 ICPC 南京 F题 Paper Grading

    题目链接 题意 给一些字符串,一个操作是交换两个串的位置,另一个是问编号介于 [l,r][l,r][l,r] 的字符串,与提问串的最长公共前缀(LCP)至少为 kkk 的个数 题解 将串建立 Trie ...

  5. 2019年秦皇岛J题:MUV LUV EXTRA(KMP后缀数组)

    Problem Description 鉴纯夏是一名成绩不太好的高中生.一天她在数学考试中碰到了一道求某条线段长度的问题.因为她并不会做这道题,所以她准确地作图后用尺子量出了这条线段的长度.不幸的是, ...

  6. 2019 CCPC秦皇岛 J 题 MUV LUV EXTRA【KMP 求最小循环节】

    题意: 原题意是给出一个有理数的前一部分,求这个有理数的无限循环部分是什么.有一个值来评估猜的准确度.转换一下就成了下面的题意: 给出一个字符串s,有某一个子串,设p为该子串在s的某个后缀中的匹配长度 ...

  7. 2021 ICPC 沈阳赛区J题 Luggage Lock

    2021 ICPC 沈阳赛区J题 Luggage Lock 题意 有TTT组样例,其中每组样例为: 给定一个密码为b0b1b2b3b_0b_1b_2b_3b0​b1​b2​b3​的密码锁,已知当前密码 ...

  8. 2019 ICPC 徐州网络赛 J.Random Access Iterator

    2019 ICPC 徐州网络赛 J.Random Access Iterator 题目大意:给你n个点和n-1条边(树形结构),保证1为根节点,通过以下方式dfs遍历: 询问dfs到最深节点的概率(有 ...

  9. 2019 ICPC全国邀请赛(西安)I. Cracking Password(序列检验,BSGS,细节题)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 2019 ICPC全国邀请赛(西安)I. Cracking Password Weblink http ...

最新文章

  1. java加减乘除运算代码_从“位运算”炫技到“操作符”,再到逐步理解“群论”...
  2. tomcat如何将请求分发到servlet
  3. 多线程与网络之NSURLConnection发送请求
  4. abaqus失效单元删除_[转载]abaqus单元删除的一般方法
  5. Handler+MessageQueue等操作
  6. 前后端api参考手册
  7. 软考高项之项目变更管理
  8. 怎么将多张图片合成一个pdf文件
  9. CSS消除absolute 的影响
  10. 【已解决】微信内置浏览器清缓存
  11. 杂记二 · 永远不服输
  12. 大型水利投资集团,打造数智财资管理新范式
  13. 应用在电力行业的无源RFID温度传感器标签
  14. 【20210827】【系统设计】“秒杀系统”架构设计分析
  15. python编程:从入门到实践习题第五章5-8~5-11
  16. python3小项目——爬取智联招聘信息(二)
  17. 步数精灵v3.0运动安卓版
  18. python-布尔运算
  19. Unity3d AssetBundle依赖关系获取
  20. AI笔记: 数学基础之矩阵的初等变换计算矩阵的秩

热门文章

  1. Kaggle | 金融交易欺诈检测(Synthetic Financial Datasets For Fraud Detection)
  2. 计算机的发展史英语作文,选择一种计算机英语作文:求一篇关于计算机发展史的英语作文...
  3. 大数据这么火,什么是大数据呢?-大萝卜博客网
  4. [译]百里挑一:21个优质Swift开源App
  5. 使用计算机配置路由器,用命令配置路由器基础(
  6. 数据仓库 python_python新手如何通过即时转换彻底改变收藏的数据仓库
  7. 渐进式复杂度分析-学习笔记
  8. HTML第二天学习笔记
  9. Python----稀疏矩阵
  10. Havok物理引擎_百度百科