[BZOJ2594] [Wc2006]水管局长数据加强版(LCT + kruskal + 离线)
WC这个题真是丧心病狂啊,就是想学习一下怎么处理边权,给我来了这么一个破题!
ORZ hzwer 临摹黄学长代码233 但还是复杂的一匹
理一下思路吧
题目大意:给定一个无向图,多次删除图中的某一条边,求两点间路径最大值的最小值
求两点间的路径最大值的最小值的话,可以求最小生成树,那么这个值就是最小生成树上两点间路径上的最大值
但是题目要求是删除边,LCT维护最小生成树不支持删边操作,那么就离线处理,倒着加边,用LCT维护。
就是这个离线处理是最恶心的。
来说说如何处理边权,把边也抽象成点,那么这个点就和原来边所连的两个点相连,其中边抽象成的点点权为边权,所连接的两个点点权为 0
给边从小到大排序,那么边所抽象成的点的序号即为 边的序号 + n (n 为原来点的个数)
然后再将边按照它所连的两个点为关键字排序,二分查找确定所删除的边的序号。
再按照从小到大的顺序再排回来,跑 kruskal,依次添加没有被删除的边
最后从后往前处理询问,添加一条边的时候先判断两端点是否连通(当然此题不必,因为题目中说:任何时候我们考虑的水管网络都是连通的,即从任一结点A必有至少一条水管路径通往任一结点B。。所以肯定连通)
然后找出两点间路径边权的最大的,判断最大的边权是否大于要加入的边的边权,如果大于,就删除这条边,连接新边,否则就不加入(维护最小生成树)
具体细节看代码
——代码
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- #define N 1500005
- #define get(x) (son[f[x]][1] == (x))
- #define swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
- #define isroot(x) (son[f[x]][0] ^ (x) && son[f[x]][1] ^ (x))
- int n, m, Q, tot;
- int mx[N], rev[N], fa[N], f[N], val[N], son[N][], s[N];
- struct node
- {
- int x, y, z, id;
- bool d;
- }e[N];
- struct ask
- {
- int f, x, y, ans, id;
- }q[N];
- inline int read()
- {
- int x = , f = ;
- char ch = getchar();
- for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
- for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
- return x * f;
- }
- inline bool cmp1(node x, node y)
- {
- return x.z < y.z;
- }
- inline bool cmp2(node x, node y)
- {
- return x.x < y.x || (x.x == y.x && x.y < y.y);
- }
- inline bool cmp3(node x, node y)
- {
- return x.id < y.id;
- }
- inline int getf(int x)
- {
- return x == fa[x] ? x : fa[x] = getf(fa[x]);
- }
- inline int find(int x, int y)
- {
- int l = , r = m, mid;
- while(l <= r)
- {
- mid = (l + r) >> ;
- if(e[mid].x < x || (e[mid].x == x && e[mid].y < y)) l = mid + ;
- else if(e[mid].x == x && e[mid].y == y) return mid;
- else r = mid - ;
- }
- }
- inline void update(int x)
- {
- if(x)
- {
- mx[x] = x;
- if(son[x][] && val[mx[son[x][]]] > val[mx[x]]) mx[x] = mx[son[x][]];
- if(son[x][] && val[mx[son[x][]]] > val[mx[x]]) mx[x] = mx[son[x][]];
- }
- }
- inline void pushdown(int x)
- {
- if(x && rev[x])
- {
- swap(son[x][], son[x][]);
- if(son[x][]) rev[son[x][]] ^= ;
- if(son[x][]) rev[son[x][]] ^= ;
- rev[x] = ;
- }
- }
- inline void rotate(int x)
- {
- int old = f[x], oldf = f[old], wh = get(x);
- if(!isroot(old))
- son[oldf][get(old)] = x;
- f[x] = oldf;
- son[old][wh] = son[x][wh ^ ];
- f[son[old][wh]] = old;
- son[x][wh ^ ] = old;
- f[old] = x;
- update(old);
- update(x);
- }
- inline void splay(int x)
- {
- int i, fat, t = ;
- s[++t] = x;
- for(i = x; !isroot(i); i = f[i]) s[++t] = f[i];
- for(i = t; i; i--) pushdown(s[i]);
- for(; !isroot(x); rotate(x))
- if(!isroot(fat = f[x]))
- rotate(get(x) ^ get(fat) ? x : fat);
- }
- inline void access(int x)
- {
- for(int t = ; x; t = x, x = f[x]) splay(x), son[x][] = t, update(x);
- }
- inline void reverse(int x)
- {
- access(x);
- splay(x);
- rev[x] ^= ;
- }
- inline void cut(int x, int y)
- {
- reverse(x);
- access(y);
- splay(y);
- son[y][] = f[x] = ;
- update(y);
- }
- inline void link(int x, int y)
- {
- reverse(x);
- f[x] = y;
- access(x);
- }
- inline int query(int x, int y)
- {
- reverse(x);
- access(y);
- splay(y);
- return mx[y];
- }
- int main()
- {
- int i, j, k, t, x, y, fx, fy;
- n = read();
- m = read();
- Q = read();
- for(i = ; i <= n; i++) fa[i] = i;
- for(i = ; i <= m; i++)
- {
- e[i].x = read();
- e[i].y = read();
- e[i].z = read();
- if(e[i].x > e[i].y) swap(e[i].x, e[i].y);
- }
- std::sort(e + , e + m + , cmp1);
- for(i = ; i <= m; i++)
- {
- e[i].id = i;
- val[n + i] = e[i].z;
- mx[n + i] = n + i;
- }
- std::sort(e + , e + m + , cmp2);
- for(i = ; i <= Q; i++)
- {
- q[i].f = read();
- q[i].x = read();
- q[i].y = read();
- if(q[i].x > q[i].y) swap(q[i].x, q[i].y);
- if(q[i].f == )
- {
- t = find(q[i].x, q[i].y);
- e[t].d = ;
- q[i].id = e[t].id;
- }
- }
- std::sort(e + , e + m + , cmp3);
- for(i = ; i <= m; i++)
- if(!e[i].d)
- {
- x = e[i].x;
- y = e[i].y;
- fx = getf(x);
- fy = getf(y);
- if(fx ^ fy)
- {
- fa[fx] = fy;
- link(x, i + n);
- link(y, i + n);
- tot++;
- if(tot == n - ) break;
- }
- }
- for(i = Q; i; i--)
- {
- if(q[i].f == ) q[i].ans = val[query(q[i].x, q[i].y)];
- else
- {
- x = q[i].x;
- y = q[i].y;
- k = q[i].id;
- t = query(x, y);
- if(e[k].z < val[t])
- {
- cut(e[t - n].x, t);
- cut(e[t - n].y, t);
- link(x, k + n);
- link(y, k + n);
- }
- }
- }
- for(i = ; i <= Q; i++)
- if(q[i].f == )
- printf("%d\n", q[i].ans);
- return ;
- }
[BZOJ2594] [Wc2006]水管局长数据加强版(LCT + kruskal + 离线)的更多相关文章
- BZOJ2594 [Wc2006]水管局长数据加强版 LCT kruskal
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2594 题意概括 N个点的图,M条带权边.(N<=100000,M<=1000000) ...
- [bzoj2594][Wc2006]水管局长数据加强版 (lct)
论蒟蒻的自我修养T_T.. 和noi2014魔法森林基本一样...然而数据范围大得sxbk...UPD:这题如果用lct判联通的话可能会被卡到O(mlogm)..所以最好还是用并查集吧 一开始数组开太 ...
- BZOJ 2594: [Wc2006]水管局长数据加强版 [LCT kruskal]
2594: [Wc2006]水管局长数据加强版 Time Limit: 25 Sec Memory Limit: 128 MBSubmit: 2917 Solved: 918[Submit][St ...
- [bzoj2594][Wc2006]水管局长数据加强版——lct+离线
Brief Description 您有一个无向带权图,您需要支持两种操作. 询问两个点之间的最大权最小路径. 删除一条边. Algorithm Design 我们首先提出一个猜想:最优路径一定在原图 ...
- bzoj2594 [Wc2006]水管局长数据加强版——LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2594 时间倒序一下,就是 魔法森林 那道题: 有个不解的地方,是 access 里面关于 p ...
- BZOJ2594: [Wc2006]水管局长数据加强版
题解: 裸LCT+离线+二分+MST... 代码:(几乎摘抄自hzwer) #include<cstdio> #include<cstdlib> #include<cma ...
- BZOJ 2594: [Wc2006]水管局长数据加强版( LCT )
离线然后就是维护加边的动态MST, Link cut tree秒掉..不过我写+调了好久...时间复杂度O(NlogN + MlogM) ------------------------------- ...
- BZOJ2594 [Wc2006]水管局长数据加强版 【LCT维护最小生成树】
题目 SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一条从A至B的水管的 ...
- BZOJ 2594: [Wc2006]水管局长数据加强版(kruskal + LCT)
Description SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一 ...
随机推荐
- hdu 1043 Eight
欸我一直以为双向bfs是搜完一半再搜另一半呢,妹想到是两个一起搜 然后队列里放的结构体里不能直接存答案,所以做一个邻接表一样的东西,直接指向需要的字符即可 记录状态用康托展开来hash 以及居然是多组 ...
- bzoj 1635: [Usaco2007 Jan]Tallest Cow 最高的牛【差分】
s[i]为差分后的"i这头牛前有几头比它高",计算答案的时候加成前缀和,假设第一头最高减一下即可 用map记录一下被加过的区间,避免重复 #include<iostream& ...
- VUE学习之计算属性computed
计算属性:computed 先看一下官网的说法 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护.例如: <div id="ex ...
- 【工具】---- json-server基本使用
一.概念 在开发过程中,前端通常需要等待后端开发完接口后,再调用接口渲染相应的数据,这会影响开发效率.而json-server的作用就是为了解决前后端并行开发的痛点,在本地模拟后端接口用来测试前端效果 ...
- mysql之replace into与 insert into duplicat key for update
mysql实际应用中,我们在插入数据的时候,经常遇到主键冲突的情况,这是因为库中已经存在相同主键的数据,这时,我们只能更新数据:在判断是更新数据还是插入数据,我们还需要在此之前做一些必要的判断:在my ...
- C++帮助文档(自己写的)
以下所有记录几乎都是摘抄自<C++ primer 5th 中文> auto 类型说明符 P61 特点: 1. 定义的变量必须有初始值 2. 通过初始值来推算变量的类 ...
- Java设置全局热键——第三方包jintellitype实现
Java原生API并不支持为应用程序设置全局热键.要实现全局热键,需要用JNI方式实现,这就涉及到编写C/C++代码,这对于大多数不熟悉C/C++的javaer来说,有点困难.不过幸好,国外有人已经实 ...
- 求助:可以使用任何编程工具做成一个控件或组件,使得在VB中能调用并得到摄像头的参数及图片。
请看下网址上的这个问题,看是否有解决的方式http://www.educity.cn/wenda/338634.html
- npm——nrm
nrm 是镜像地址,方便国内下载 npm i nrm -g nrm ls nrm use taobao // 切换地址
- linux环境下为php7装phpredis扩展
phpredis在php7.php5下都有不同的版本,装岔了可能会编译报错,所以在安装之前请先看下自己的php是啥版本. 我的redis装的是redis3.2.3版本. 用phpinfo()查看安装的 ...