Input

Output

Sample Input

  1. 4 5
  2. 1 2
  3. 2 3
  4. 3 4
  5. 4 1
  6. 2 4
  7. 3
  8. 1 5
  9. 2 2 3
  10. 2 1 2

Sample Output

  1. Connected
  2. Disconnected
  3. Connected

Hint

N<=100000 M<=200000 K<=100000


  题目大意 给出一个有n个节点和m条边的图,然后有k个询问,每个询问是删掉一些边,然后判断图是否连通,询问之间互相独立。

  连通性问题通常的做法是并查集,然而并查集不支持删边,但是可以撤销上次操作,所以只能考虑把一条一条边加入并查集,为了高效的确定边是否存在,可以用一个时间戳(其实就是确定某条边在询问时是否存在)。因为存在的时间段是连续的,所以呢就用一个线段树,每个点开一个vector,记录恰好存在时间段为当前区间的的边有哪些。

  接着开始遍历整棵树,每到一个点就把它存的边一一塞进并查集

  1)如果不是叶节点,然后访问左右子树,访问完后O(1)撤销这个点加入的所有边

  2)如果是叶节点,就随便找个点的最高级father(就是f[father] = father)看下它的size是否为n(然后一个操作就"水"完了)

  因为并查集要支持撤销,所以不能压缩路径了,只能按秩合并(把小的合并到大的中)。

  注意题目输入中的数据范围是错的(然后我就RE了一次)

Code

  1. /**
  2. * bzoj
  3. * Problem#3237
  4. * Accepted
  5. * Time:19508ms
  6. * Memory:72656k
  7. */
  8. #include <iostream>
  9. #include <cstdio>
  10. #include <ctime>
  11. #include <cmath>
  12. #include <cctype>
  13. #include <cstring>
  14. #include <cstdlib>
  15. #include <fstream>
  16. #include <sstream>
  17. #include <algorithm>
  18. #include <map>
  19. #include <set>
  20. #include <stack>
  21. #include <queue>
  22. #include <vector>
  23. #include <stack>
  24. #ifndef WIN32
  25. #define Auto "%lld"
  26. #else
  27. #define Auto "%I64d"
  28. #endif
  29. using namespace std;
  30. typedef bool boolean;
  31. const signed int inf = (signed)((1u << ) - );
  32. const signed long long llf = (signed long long)((1ull << ) - );
  33. const double eps = 1e-;
  34. const int binary_limit = ;
  35. #define smin(a, b) a = min(a, b)
  36. #define smax(a, b) a = max(a, b)
  37. #define max3(a, b, c) max(a, max(b, c))
  38. #define min3(a, b, c) min(a, min(b, c))
  39. template<typename T>
  40. inline boolean readInteger(T& u){
  41. char x;
  42. int aFlag = ;
  43. while(!isdigit((x = getchar())) && x != '-' && x != -);
  44. if(x == -) {
  45. ungetc(x, stdin);
  46. return false;
  47. }
  48. if(x == '-'){
  49. x = getchar();
  50. aFlag = -;
  51. }
  52. for(u = x - ''; isdigit((x = getchar())); u = (u * ) + x - '');
  53. ungetc(x, stdin);
  54. u *= aFlag;
  55. return true;
  56. }
  57.  
  58. typedef class SegTreeNode {
  59. public:
  60. vector< pair<int, int> > e;
  61. SegTreeNode *l, *r;
  62.  
  63. SegTreeNode() { }
  64. SegTreeNode(SegTreeNode* l, SegTreeNode* r):l(l), r(r) { }
  65. }SegTreeNode;
  66.  
  67. SegTreeNode pool[];
  68. SegTreeNode *top = pool;
  69. SegTreeNode null = SegTreeNode(&null, &null);
  70.  
  71. inline SegTreeNode* newnode() {
  72. *top = SegTreeNode(&null, &null);
  73. return top++;
  74. }
  75.  
  76. typedef class union_found {
  77. public:
  78. int n;
  79. SegTreeNode* root;
  80. int* f;
  81. int* s;
  82. stack< pair<int, int> > trace;
  83. stack< pair<int, int> > ss;
  84. union_found():root(NULL) { }
  85. union_found(int n):root(&null), n(n) {
  86. f = new int[(n + )];
  87. s = new int[(n + )];
  88. fill(s, s + n + , );
  89. for(int i = ; i <= n; i++)
  90. f[i] = i;
  91. }
  92.  
  93. int find(int x) {
  94. return (f[x] == x) ? (x) : (find(f[x]));
  95. }
  96.  
  97. inline void unit(int fa, int so) {
  98. int ffa = find(fa);
  99. int fso = find(so);
  100. if(ffa == fso) trace.push(pair<int, int>(, ));
  101. else {
  102. if(s[ffa] < s[fso])
  103. swap(ffa, fso);
  104. trace.push(pair<int, int>(fso, f[fso]));
  105. ss.push(pair<int, int>(ffa, s[ffa]));
  106. s[ffa] += s[fso];
  107. f[fso] = ffa;
  108. }
  109. }
  110.  
  111. inline void undo() {
  112. pair<int, int> p = trace.top();
  113. pair<int, int> sp = ss.top();
  114. trace.pop();
  115. if(p.first == ) return;
  116. f[p.first] = p.second;
  117. s[sp.first] = sp.second;
  118. ss.pop();
  119. }
  120.  
  121. void update(SegTreeNode*& node, int l, int r, int ql, int qr, pair<int, int> &val) {
  122. if(node == &null) node = newnode();
  123. if(l == ql && r == qr) {
  124. // printf("Update at segment [%d, %d] with the edge (%d, %d)\n", l, r, val.first, val.second);
  125. node->e.push_back(val);
  126. return;
  127. }
  128. int mid = (l + r) >> ;
  129. if(qr <= mid) update(node->l, l, mid, ql, qr, val);
  130. else if(ql > mid) update(node->r, mid + , r, ql, qr, val);
  131. else {
  132. update(node->l, l, mid, ql, mid, val);
  133. update(node->r, mid + , r, mid + , qr, val);
  134. }
  135. }
  136.  
  137. void query(SegTreeNode* node, int l, int r, boolean *res) {
  138. pair<int, int> p;
  139. for(int i = ; i < (signed)node->e.size(); i++) {
  140. p = node->e[i];
  141. unit(p.first, p.second);
  142. // printf("Connect %d and %d\n", p.first, p.second);
  143. }
  144. if(l == r) {
  145. res[l] = (s[find()] == n);
  146. } else {
  147. int mid = (l + r) >> ;
  148. query(node->l, l, mid, res);
  149. query(node->r, mid + , r, res);
  150. }
  151. for(int i = ; i < (signed)node->e.size(); i++)
  152. undo();
  153. }
  154. }union_found;
  155.  
  156. int n, m, q;
  157. pair<int, int> *es;
  158. vector<int> *exists;
  159. union_found uf;
  160.  
  161. inline void init() {
  162. readInteger(n);
  163. readInteger(m);
  164. es = new pair<int, int>[(m + )];
  165. for(int i = ; i <= m; i++) {
  166. readInteger(es[i].first);
  167. readInteger(es[i].second);
  168. }
  169. exists = new vector<int>[(m + )];
  170. readInteger(q);
  171. for(int i = , c, x; i <= q; i++) {
  172. readInteger(c);
  173. while(c--) {
  174. readInteger(x);
  175. exists[x].push_back(i);
  176. }
  177. }
  178. }
  179.  
  180. inline void mktree() {
  181. uf = union_found(n);
  182. for(int i = ; i <= m; i++) {
  183. exists[i].push_back(q + );
  184. for(int j = , last = ; j < (signed)exists[i].size(); j++) {
  185. if(last == exists[i][j])
  186. last++;
  187. else {
  188. // cout << exists[i][j] << endl;
  189. uf.update(uf.root, , q, last, exists[i][j] - , es[i]);
  190. last = exists[i][j] + ;
  191. }
  192. }
  193. }
  194. }
  195.  
  196. boolean *res;
  197. inline void solve() {
  198. res = new boolean[(q + )];
  199. uf.query(uf.root, , q, res);
  200. for(int i = ; i <= q; i++)
  201. puts((res[i]) ? ("Connected") : ("Disconnected"));
  202. }
  203.  
  204. int main() {
  205. init();
  206. mktree();
  207. solve();
  208. return ;
  209. }

bzoj 3237 连通图 - 并查集 - 线段树的更多相关文章

  1. BZOJ 3910 并查集+线段树合并

    思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...

  2. UVA1455 - Kingdom(并查集 + 线段树)

    UVA1455 - Kingdom(并查集 + 线段树) 题目链接 题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum ...

  3. 并查集&线段树&树状数组&排序二叉树

    超级无敌巨牛逼并查集(带权并查集)https://vjudge.net/problem/UVALive-4487 带删点的加权并查集 https://vjudge.net/problem/UVA-11 ...

  4. 【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)

    题目 CF576E 分析: 从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下. 首先做这题之前推荐一道很相似的题:[BZOJ4025]二分图(可撤销并查集+线段树 ...

  5. bzoj 2733 永无乡 - 并查集 - 线段树

    永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛. ...

  6. BZOJ 3319 黑白树 并查集+线段树

    这这这这这这什么毒瘤题!!!!!!!!!!!!!!!!!!!!!!!!!!!! 卡LCT(优秀的LCT由于是均摊本身就带着2,3的常数在,而且这道题对于LCT标记十分难维护,又得乘上4,5然后就炸了) ...

  7. 并查集 + 线段树 LA 4730 Kingdom

    题目传送门 题意:训练指南P248 分析:第一个操作可以用并查集实现,保存某集合的最小高度和最大高度以及城市个数.运用线段树成端更新来统计一个区间高度的个数,此时高度需要离散化.这题两种数据结构一起使 ...

  8. YYHS-猜数字(并查集/线段树维护)

    题目描述     LYK在玩猜数字游戏.    总共有n个互不相同的正整数,LYK每次猜一段区间的最小值.形如[li,ri]这段区间的数字的最小值一定等于xi.     我们总能构造出一种方案使得LY ...

  9. luogu5012 水の数列 (并查集+线段树)

    如果我们能求出来每个区间个数的最大分值,那就可以用线段树维护这个东西 然后出答案了 然后这个的求法和(luogu4269)Snow Boots G非常类似,就是我们把数大小排个序,每次都拿<=x ...

随机推荐

  1. cocos2d-x JS 获取屏幕大小或中点

    以一张背景图为例: var HelloWorldLayer = cc.Layer.extend({ ctor:function () { this._super(); var bg = new cc. ...

  2. SignalR WebSocket Error during WebSocket handshake: net::ERR_CONNECTION_RESET

    system.web 节点添加: <httpRuntime maxRequestLength="104857600" executionTimeout="1200& ...

  3. Koa中设置中文Cookie值

    默认情况下, 如果 ctx.cookies.set('user', '杨过', { domain: 'xxxx', path: 'xxxx', maxAge: 24 * 60 * 60 * 1000, ...

  4. 函数max()优化

    函数max的优化 用途:查询最后支付时间-优化max函数 语句: select max(payment_date)from payment 执行计划:

  5. LeetCode14.最长公共前缀

    编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow" ...

  6. netcore webapi统一配置跨域问题

    修改startup类中的configure方法

  7. Beta阶段冲刺前计划与安排

    凡事预则立,在Beta开始前,以小组为单位,在敏捷冲刺前发布一篇博客,描述: 1. 介绍小组新加入的成员,Ta担任的角色. 新加入的成员是丁蓉同学,在本团队中担任前端设计. 原因:在之前的团队中,她就 ...

  8. linux设置时间显示格式和系统版本

    [修改显示日期格式] vim /etc/bashrc alias ll='ls -l --time-style="+%Y-%m-%d %H:%M:%S"' alias date=' ...

  9. Codeforces Round #324 (Div. 2) E

    这题贪心,考虑先放第一个,然后从第一个数在p中的位置, 不断的往前走,和在他后面的那些数组进行交换,因为这样交换可以提高最大的效率,就是说你花费了1但是使得两个点都朝他的木匾节点减少了1 #inclu ...

  10. mysql使用navicat编写调用存储过程

    在Navicat里面,找到函数,右键,新建函数,选择过程,如果有参数就填写函数,如果没有就直接点击完成 在BEGIN......END中间编写要执行的sql语句,例如下面存储过程取名为pro_data ...