欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ2594


题意概括

  N个点的图,M条带权边。(N<=100000,M<=1000000)

  有Q次操作(Q<=100000)

  操作有两个类型:

  1.问节点x到y的路径中边的最大权值。

  2.删除某一条边

  操作过程中保证图连通


题解

  我们发现很难做。

  能够1A也是我运气好。

  我们发现顺着做貌似很难,要找到边,然后删掉……

  这题是LCT的,显然不会在图上做。

  看了看网上的题解,懂了。

  倒着来,把删边看作加边。

  假如没有删边或者加边的操作,那么有用的边一定是最小生成树上的。

  换句话说就是a~b中路径的最大权值最小的边一定在当前最小生成树上。

  于是我们倒着维护一棵最小生成树。

  每次加入一条边,连接x和y,权值为z,我们要找到x和y的路径中权值最大的边。

  然后把他删掉,再添入当前边(当然这个权值最大的可能是他自己,那么什么都不干了)。

  这个贪心的思想应该不用讲了吧。

  现在是关键是怎么做。

  我们考虑用LCT来维护。

  但是LCT只可以维护点权,很难做到维护边权。

  所以我们化边为点。

  我们把每一条边看作一个点。

  然后比如说第k条边连接了x和y,那么连上第k条边的时候,我们就分别link(x,k)和link(y,k)

  然后就达到了连接点的同样的效果。

  那么,再写一个LCT维护一下最大值就可以了。

  这里有一个小技巧,就是记录最大值编号。

  还有一个查询边的问题,那么我们可以给边按照节点排个序,然后二分查找即可。

  这个可以事先处理好。

  详见代码


代码

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=100005,M=1000005,S=N+M;
bool isd(char ch){
return '0'<=ch&&ch<='9';
}
void read(int &x){
x=0;
char ch=getchar();
while (!isd(ch))
ch=getchar();
while (isd(ch))
x=x*10+ch-48,ch=getchar();
}
int n,m,Q,s;
int fa[S],son[S][2],rev[S],val[S],Max[S];
int ans[N];
struct Three{
int x,y,z,flag;
void Read(int flag){
read(x),read(y),read(z);
if (flag&&x>y)
swap(x,y);
flag=0;
}
}e[M],q[N];
bool cmp1(Three a,Three b){
return (a.x==b.x&&a.y<b.y)||a.x<b.x;
}
bool cmp2(Three a,Three b){
return a.z<b.z;
}
void clear(int x,int v){
fa[x]=son[x][0]=son[x][1]=rev[x]=0;
val[x]=Max[x]=v;
}
int search(int a,int b){
if (a>b)
swap(a,b);
int L=1,R=m,mid;
while (L<=R){
mid=(L+R)>>1;
if (e[mid].x==a&&e[mid].y==b)
return mid;
if ((e[mid].x==a&&e[mid].y<b)||e[mid].x<a)
L=mid+1;
else
R=mid-1;
}
}
bool isroot(int x){
return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
void pushup(int x){
int LMax=Max[son[x][0]],RMax=Max[son[x][1]];
Max[x]=e[LMax].z>e[RMax].z?LMax:RMax;
Max[x]=e[val[x]].z>e[Max[x]].z?val[x]:Max[x];
}
void pushdown(int x){
if (rev[x]){
rev[x]=0;
rev[son[x][0]]^=1;
rev[son[x][1]]^=1;
swap(son[x][0],son[x][1]);
}
}
void pushadd(int x){
if (!isroot(x))
pushadd(fa[x]);
pushdown(x);
}
int wson(int x){
return son[fa[x]][1]==x;
}
void rotate(int x){
if (isroot(x))
return;
int y=fa[x],z=fa[y],L=wson(x),R=L^1;
if (!isroot(y))
son[z][wson(y)]=x;
fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
son[y][L]=son[x][R],son[x][R]=y;
pushup(y),pushup(x);
}
void splay(int x){
pushadd(x);
for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
if (!isroot(y))
rotate(wson(x)==wson(y)?y:x);
}
void access(int x){
int t=0;
while (x){
splay(x);
son[x][1]=t;
pushup(x);
t=x;
x=fa[x];
}
}
void rever(int x){
access(x);
splay(x);
rev[x]^=1;
}
void link(int x,int y){
rever(x);
fa[x]=y;
}
void split(int x,int y){//让y做x的左儿子
rever(y);
access(x);
splay(x);
}
void cut(int x,int y){
split(y,x);
fa[x]=son[y][0]=0;
}
int find(int x){
access(x);
splay(x);
while (1){
pushdown(x);
if (son[x][0])
x=son[x][0];
else
break;
}
return x;
}
int main(){
read(n),read(m),read(Q);
for (int i=1;i<=m;i++)
e[i].Read(1);
for (int i=1;i<=Q;i++)
q[i].Read(0);
sort(e+1,e+m+1,cmp1);
for (int i=1;i<=Q;i++)
if (q[i].x==2)
e[search(q[i].y,q[i].z)].flag=i;
sort(e+1,e+m+1,cmp2);
for (int i=1;i<=m;i++)
if (e[i].flag)
q[e[i].flag].flag=i;
s=n+m;
for (int i=1;i<=s;i++)
clear(i,i<=n?0:(i-n));
e[0].z=0;
for (int i=1,j=1;i<=m&&j<n;i++){
if (e[i].flag)
continue;
int x=e[i].x,y=e[i].y;
if (find(x)==find(y))
continue;
link(x,i+n);
link(y,i+n);
j++;
}
for (int i=Q;i>=1;i--){
int k=q[i].x,x=q[i].y,y=q[i].z;
if (k==1){
split(x,y);
ans[i]=e[Max[x]].z;
}
if (k==2){
split(x,y);
int cE=Max[x],aE=q[i].flag;
if (e[cE].z>e[aE].z){
cut(e[cE].x,cE+n);
cut(e[cE].y,cE+n);
link(e[aE].x,aE+n);
link(e[aE].y,aE+n);
}
}
}
for (int i=1;i<=Q;i++)
if (q[i].x==1)
printf("%d\n",ans[i]);
return 0;
}

  

BZOJ2594 [Wc2006]水管局长数据加强版 LCT kruskal的更多相关文章

  1. [bzoj2594][Wc2006]水管局长数据加强版 (lct)

    论蒟蒻的自我修养T_T.. 和noi2014魔法森林基本一样...然而数据范围大得sxbk...UPD:这题如果用lct判联通的话可能会被卡到O(mlogm)..所以最好还是用并查集吧 一开始数组开太 ...

  2. BZOJ 2594: [Wc2006]水管局长数据加强版 [LCT kruskal]

    2594: [Wc2006]水管局长数据加强版 Time Limit: 25 Sec  Memory Limit: 128 MBSubmit: 2917  Solved: 918[Submit][St ...

  3. [bzoj2594][Wc2006]水管局长数据加强版——lct+离线

    Brief Description 您有一个无向带权图,您需要支持两种操作. 询问两个点之间的最大权最小路径. 删除一条边. Algorithm Design 我们首先提出一个猜想:最优路径一定在原图 ...

  4. bzoj2594 [Wc2006]水管局长数据加强版——LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2594 时间倒序一下,就是 魔法森林 那道题: 有个不解的地方,是 access 里面关于 p ...

  5. BZOJ2594: [Wc2006]水管局长数据加强版

    题解: 裸LCT+离线+二分+MST... 代码:(几乎摘抄自hzwer) #include<cstdio> #include<cstdlib> #include<cma ...

  6. BZOJ 2594: [Wc2006]水管局长数据加强版( LCT )

    离线然后就是维护加边的动态MST, Link cut tree秒掉..不过我写+调了好久...时间复杂度O(NlogN + MlogM) ------------------------------- ...

  7. BZOJ2594 [Wc2006]水管局长数据加强版 【LCT维护最小生成树】

    题目 SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一条从A至B的水管的 ...

  8. BZOJ 2594: [Wc2006]水管局长数据加强版(kruskal + LCT)

    Description SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一 ...

  9. [BZOJ2594] [Wc2006]水管局长数据加强版(LCT + kruskal + 离线)

    传送门 WC这个题真是丧心病狂啊,就是想学习一下怎么处理边权,给我来了这么一个破题! ORZ hzwer 临摹黄学长代码233 但还是复杂的一匹 理一下思路吧 题目大意:给定一个无向图,多次删除图中的 ...

随机推荐

  1. u-boot移植(二)---修改前工作:代码流程分析1

    一.代码执行总体流程图 1.1 代码路径 U-boot.lds (arch\arm\cpu) vectors.S (arch\arm\lib) start.S (arch\arm\cpu\arm920 ...

  2. linux4.10.8 内核移植(四)---字符设备驱动_led驱动程序

    一.字符设备驱动程序介绍 app里面用 open.read.write等等函数出来操作底层硬件.驱动程序中也有对应的xxx_open等函数.怎么找到驱动程序中的函数依赖于驱动程序框架. 二.搭建驱动程 ...

  3. div 只显示两行超出部分隐藏

    ; -webkit-box-orient: vertical;line-height: 26px } <td rowspan="2" colspan="2" ...

  4. 让 IE9 以下的浏览器支持 Media Queries

    1. 如何让 IE9 以下的浏览器支持 css3 的media query 需要用到的 min-width/max-width 属性 css3 的媒体查询 IE 浏览器的支持程度是从 IE9开始支持, ...

  5. systemctl命令是系统服务管理器指令,它实际上将 service 和 chkconfig 这两个命令组合到一起。

    1.centos 检查服务是否开机自启  (ntpd是原生的服务,mysql是注册的服务) 参考:1.http://man.linuxde.net/systemctl

  6. UML和模式应用4:初始阶段(1)--概述

    1.前言 UP开发包括四个阶段:初始阶段.细化阶段.构建阶段.移交阶段: 初始阶段是项目比较简短的起始步骤,主要目的是收集足够的信息来建立共同设想,调查项目的总体目标和可行性,确定是否值得进一步深入. ...

  7. oracle ip 改为 机器名

    1 hosts文件 添加                   ip  机器名   这一行 2 修改listner.ora 和tnsora.ora ip改为机器名 3 重启服务

  8. centos7 部署 docker ce

    =============================================== 2019/4/9_第1次修改                       ccb_warlock === ...

  9. python读取两个csv文件数据,进行查找匹配出现次数

    现有需求 表1 表2 需要拿表1中的编码去表2中的门票编码列匹配,统计出现的次数,由于表2编码列是区域间,而且列不是固定的,代码如下 #encoding:utf-8 ##导入两个CSV进行比对 imp ...

  10. python3内存存储几种数据类型对差异

    列表,元组,集合,字典几种数据类型差异 列表: list=[0,1,'a'] 元组:list=(0,1,'a') 集合 :list=[0,1,'a'] 字典:list={name:'tom',age: ...