题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458

给你n个点,m条边,q个操作,操作1是删边,操作2是问u到v之间的割边有多少条。

这题要倒着做才容易,倒着加边。

因为这题最后保证所有的点一定连通,所以可以构建一棵树,树链剖分一下。要是u到v之间只有一条边,那便是一条割边。而加边的话,就是将u到v之间的边权都+1,边权等于1的话是桥,大于1的话就不是了。所以我们初始化树的时候,可以将边权初始化为1,加边操作将边权赋值为0。求u到v的割边个数的话,就是求u到v的和。

中间存边我用multiset( map 超时),然后用并查集判断是不是一棵完整的树从而看情况加边。

  1. //#pragma comment(linker, "/STACK:102400000, 102400000")
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <cstdio>
  7. #include <vector>
  8. #include <cmath>
  9. #include <ctime>
  10. #include <list>
  11. #include <set>
  12. #include <map>
  13. using namespace std;
  14. typedef long long LL;
  15. typedef pair <int, int> P;
  16. const int N = 1e5 + ;
  17. struct Edge {
  18. int next, to;
  19. }edge[N << ];
  20. multiset <P> myset; //存 构建的树的边
  21. int head[N], tot;
  22. int pre[N], son[N], dep[N], size[N], cnt; //son:重儿子
  23. int top[N], id[N];
  24. int uu[N], vv[N], c[N]; //q个操作c uu vv
  25. int x[N], y[N]; //开始输入的m条边x y
  26. int ans[N]; //答案
  27. int par[N]; //并查集
  28.  
  29. void init(int n) {
  30. for(int i = ; i <= n; ++i) {
  31. par[i] = i;
  32. head[i] = -;
  33. }
  34. tot = cnt = ;
  35. myset.clear();
  36. }
  37.  
  38. inline void add(int u, int v) {
  39. edge[tot].next = head[u];
  40. edge[tot].to = v;
  41. head[u] = tot++;
  42. }
  43.  
  44. inline int search(int n) {
  45. if(n == par[n])
  46. return n;
  47. return par[n] = search(par[n]);
  48. }
  49.  
  50. void dfs1(int u, int p, int d) {
  51. dep[u] = d, size[u] = , son[u] = u, pre[u] = p;
  52. for(int i = head[u]; ~i; i = edge[i].next) {
  53. int v = edge[i].to;
  54. if(v == p)
  55. continue;
  56. dfs1(v, u, d + );
  57. if(size[v] >= size[son[u]])
  58. son[u] = v;
  59. size[u] += size[v];
  60. }
  61. }
  62.  
  63. void dfs2(int u, int p, int t) {
  64. top[u] = t, id[u] = ++cnt;
  65. if(son[u] != u)
  66. dfs2(son[u], u, t);
  67. for(int i = head[u]; ~i; i = edge[i].next) {
  68. int v = edge[i].to;
  69. if(v == p || v == son[u])
  70. continue;
  71. dfs2(v, u, v);
  72. }
  73. }
  74.  
  75. struct SegTree {
  76. int l, r, val, lazy, mid;
  77. }T[N << ];
  78.  
  79. void build(int p, int l, int r) {
  80. T[p].mid = (l + r) >> ;
  81. T[p].l = l, T[p].r = r, T[p].lazy = ;
  82. if(l == r) {
  83. T[p].val = ;
  84. return ;
  85. }
  86. build(p << , l, T[p].mid);
  87. build((p << )|, T[p].mid + , r);
  88. T[p].val = T[p << ].val + T[(p << )|].val;
  89. }
  90.  
  91. inline void pushdown(int p) {
  92. int ls = p << , rs = (p << )|;
  93. T[ls].lazy = T[rs].lazy = T[ls].val = T[rs].val = ;
  94. T[p].lazy = ;
  95. }
  96.  
  97. void update(int p, int l, int r) {
  98. if(T[p].val == )
  99. return ;
  100. if(T[p].l == l && T[p].r == r) {
  101. T[p].lazy = T[p].val = ;
  102. return ;
  103. }
  104. if(!T[p].lazy) {
  105. pushdown(p);
  106. }
  107. if(r <= T[p].mid) {
  108. update(p << , l, r);
  109. }
  110. else if(l > T[p].mid) {
  111. update((p << )|, l, r);
  112. }
  113. else {
  114. update(p << , l, T[p].mid);
  115. update((p << )|, T[p].mid + , r);
  116. }
  117. T[p].val = T[p << ].val + T[(p << )|].val;
  118. }
  119.  
  120. int query(int p, int l, int r) {
  121. if(T[p].val == )
  122. return ;
  123. if(T[p].l == l && T[p].r == r) {
  124. return T[p].val;
  125. }
  126. if(!T[p].lazy) {
  127. pushdown(p);
  128. }
  129. if(r <= T[p].mid) {
  130. return query(p << , l , r);
  131. }
  132. else if(l > T[p].mid) {
  133. return query((p << )| , l , r);
  134. }
  135. else {
  136. return query(p << , l , T[p].mid) + query((p << )| , T[p].mid + , r);
  137. }
  138. }
  139.  
  140. void change(int u, int v) {
  141. int fu = top[u], fv = top[v];
  142. while(fu != fv) {
  143. if(dep[fu] >= dep[fv]) {
  144. update(, id[fu], id[u]);
  145. u = pre[fu];
  146. fu = top[u];
  147. }
  148. else {
  149. update(, id[fv], id[v]);
  150. v = pre[fv];
  151. fv = top[v];
  152. }
  153. }
  154. if(u == v)
  155. return ;
  156. else if(dep[u] >= dep[v])
  157. update(, id[son[v]], id[u]);
  158. else
  159. update(, id[son[u]], id[v]);
  160. }
  161.  
  162. int find(int u, int v) {
  163. int fu = top[u], fv = top[v], res = ;
  164. while(fu != fv) {
  165. if(dep[fu] >= dep[fv]) {
  166. res += query(, id[fu], id[u]);
  167. u = pre[fu];
  168. fu = top[u];
  169. }
  170. else {
  171. res += query(, id[fv], id[v]);
  172. v = pre[fv];
  173. fv = top[v];
  174. }
  175. }
  176. if(u == v)
  177. return res;
  178. else if(dep[u] >= dep[v])
  179. return res + query(, id[son[v]], id[u]);
  180. else
  181. return res + query(, id[son[u]], id[v]);
  182. }
  183.  
  184. int main()
  185. {
  186. int t, n, m, q, u, v;
  187. scanf("%d", &t);
  188. for(int ca = ; ca <= t; ++ca) {
  189. scanf("%d %d %d", &n, &m, &q);
  190. init(n);
  191. for(int i = ; i <= m; ++i) {
  192. scanf("%d %d", x + i, y + i);
  193. if(x[i] > y[i])
  194. swap(x[i], y[i]);
  195. myset.insert(make_pair(x[i], y[i])); //先存边
  196. }
  197. for(int i = ; i <= q; ++i) {
  198. scanf("%d %d %d", c + i, uu + i, vv + i);
  199. if(uu[i] > vv[i])
  200. swap(uu[i], vv[i]);
  201. if(c[i] == ) {
  202. auto pos = myset.find(make_pair(uu[i], vv[i])); //去除要删的边
  203. myset.erase(pos);
  204. }
  205. }
  206. int f = ;
  207. for(auto i = myset.begin(); i != myset.end(); ++i) {
  208. u = search(i->first), v = search(i->second);
  209. if(u == v) { //不成环
  210. ++f;
  211. x[f] = i->first, y[f] = i->second; //此时的x y存的是非树也非删的边
  212. continue;
  213. }
  214. par[u] = v;
  215. add(i->first, i->second);
  216. add(i->second, i->first);
  217. }
  218. dfs1(, -, );
  219. dfs2(, -, );
  220. printf("Case #%d:\n", ca);
  221. build(, , n);
  222. for(int i = ; i <= f; ++i) {
  223. change(x[i], y[i]);
  224. }
  225. f = ;
  226. for(int i = q; i >= ; --i) {
  227. if(c[i] == ) {
  228. change(uu[i], vv[i]);
  229. }
  230. else {
  231. ans[++f] = find(uu[i], vv[i]);
  232. }
  233. }
  234. for(int i = f; i >= ; --i) {
  235. printf("%d\n", ans[i]);
  236. }
  237. }
  238. return ;
  239. }

写的我比较头痛,调试了比较久...

HDU 5458 Stability (树链剖分+并查集+set)的更多相关文章

  1. hdu 5458 Stability(树链剖分+并查集)

    Stability Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)Total ...

  2. bzoj3694: 最短路(树链剖分/并查集)

    bzoj1576的帮我们跑好最短路版本23333(双倍经验!嘿嘿嘿 这题可以用树链剖分或并查集写.树链剖分非常显然,并查集的写法比较妙,涨了个姿势,原来并查集的路径压缩还能这么用... 首先对于不在最 ...

  3. [BZOJ2238]Mst 最小生成树+树链剖分/并查集

    链接 题解 先构建出最小生成树,如果删的是非树边,直接输出答案 否则问题转化为,把该边删掉后剩下两个联通块,两个端点分别在两个块内的最小边权,LCT可以维护 不妨换一种思考方向:考虑一条非树边可以代替 ...

  4. HDU 5044 (树链剖分+树状数组+点/边改查)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变 ...

  5. HDU 3966(树链剖分+点修改+点查询)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题目大意:营地的分布成树型.每个营地都有一些人,每次修改修改一条链上的所有营地的人数,每次查询单 ...

  6. HDU 5044 Tree --树链剖分

    题意:给一棵树,两种操作: ADD1: 给u-v路径上所有点加上值k, ADD2:给u-v路径上所有边加上k,初始值都为0,问最后每个点和每条边的值,输出. 解法:树链剖分可做,剖出来如果直接用线段树 ...

  7. HDU - 3966-Aragorn' Story(树链剖分+线段树)

    链接:https://vjudge.net/problem/HDU-3966 题意: Our protagonist is the handsome human prince Aragorn come ...

  8. HDU 3966 RE 树链剖分 线段树 Aragorn's Story

    题意: 给出一棵树,每个顶点上有一个权值. 操作:选择一条路径,并将路径上所有的点的权值同时加或减某个数. 查询:某个点的当前权值 分析: 树链剖分完毕后,就是简单的线段树区间更新. 提交的时候注意要 ...

  9. HDU 5242 利用树链剖分思想进行贪心

    题目大意: 在给定带权值节点的树上从1开始不回头走到某个底端点后得到所有经过的点的权值后,这些点权值修改为0,到达底部后重新回到1,继续走,问走k次,最多能得到多少权值之和 这其实就是相当于每一次都走 ...

随机推荐

  1. 【第七篇】bootstrap的3级菜单样式,支持母版页保留打开状态

    razor视图的,母版页 依旧不多说,直接上代码 <ul class="sidebar-menu"> @for (int i = 0; i < mList.Cou ...

  2. 转载:NPOI导出到Excel表格

    NPOI开发包下载:http://pan.baidu.com/share/link?shareid=4025220936&uk=2837994235 需要命名空间 using NPOI.HSS ...

  3. 插件svn简单使用

    首先安装服务器Server 傻瓜式样操作.下一步下一步就这样完成了,选择的是个人版. 然后打开Server的图形化界面:VisualSVN Server Manager Repositories:资源 ...

  4. js获得鼠标的位置

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. VFL示例

    •[cancelButton(72)]-12-[acceptButton(50)] •取消按钮宽72point,accept按钮宽50point,它们之间间距12point • •[wideView( ...

  6. (转)python 优先队列

    #!/usr/bin/python from Queue import Queue from Queue import PriorityQueue a1='a1' a2='a2' a3='a3' a4 ...

  7. Java正则表达式之语法规则

    正则表达式是一种强大而灵活的文本处理工具,使用正则表达式能够以编程的方式,构造复杂的文本模式,并对输入的字符串进行搜索.一旦找到了匹配这些模式的部分,就能够随心所欲地它们进行处理.正则表达式提供了一种 ...

  8. 2015-10-13 晴 tcp/ip卷1

    今年看tcp/ip卷1的内容.苦和甜来自外界,坚强则来自内心,来自一个人的自我努力. 只有勤奋和积极进取的人 才会赢得成功的人生.加油

  9. Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置

    原文:http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/07/3003278.html 如果要在Linux上做j2ee开发,首先得搭建好j ...

  10. Javascript判断是否是ipad的浏览器

    ipad用的是Safari Mobile浏览器,访问的UA为: Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/5 ...