Luogu P4172 [WC2006]水管局长
题意
给定一个 \(n\) 个点 \(m\) 条边的图和 \(q\) 次操作,每次操作分为以下两种:
1 u v:查询 \(u\) 到 \(v\) 的一条路径使得边权最大的边的权值最小。2 u v:将边 \((u,v)\) 删去。
\(\texttt{Data Range:}1\leq u\leq 10^3,1\leq m,q\leq 10^5\)
题解
边权最大的边的权值最小,考虑用 \(\texttt{LCT}\) 维护原图的最小生成树。同时由于存在断边操作不好维护,所以考虑时间倒流。
首先先将所有没有被割去的边连起来,然后对于每一个割边操作,由于时间倒流了,所以在原图上连边,找新的最小生成树。
这里涉及到割掉环上边权最大的边的操作,为了更好的处理这个操作,可以在 \(\texttt{LCT}\) 上维护一个 \(mx_i\) 表示以 \(i\) 为根的子树上点权最大的是哪个。
注意到我们将原树上的边拆成了点,而原树上的点在 \(\texttt{LCT}\) 上的权值为 \(0\),所以这样做是正确的。
代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=2e5+51;
struct Edge{
ll from,to,dist;
inline bool operator <(const Edge &rhs)const
{
return dist<rhs.dist;
}
};
Edge ed[MAXN];
ll n,m,qcnt,from,to,cnt,xx;
ll dis[1051][1051],op[MAXN],x[MAXN],y[MAXN],g[1051][1051],ffa[MAXN];
ll res[MAXN],ex[MAXN];
inline ll read()
{
register ll num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
inline ll find(ll x)
{
return x==ffa[x]?x:ffa[x]=find(ffa[x]);
}
namespace LCT{
struct Node{
ll fa,mx,val,rv,sz;
ll ch[2];
};
struct LinkCutTree{
Node nd[MAXN];
ll st[MAXN];
#define ls nd[x].ch[0]
#define rs nd[x].ch[1]
inline bool nroot(ll x)
{
return nd[nd[x].fa].ch[0]==x||nd[nd[x].fa].ch[1]==x;
}
inline ll get(ll x,ll y)
{
return nd[x].val>nd[y].val?x:y;
}
inline void update(ll x)
{
nd[x].mx=get(x,get(nd[ls].mx,nd[rs].mx));
}
inline void reverse(ll x)
{
swap(ls,rs),nd[x].rv^=1;
}
inline void spread(ll x)
{
if(nd[x].rv)
{
ls?reverse(ls):(void)(1),rs?reverse(rs):(void)(1);
nd[x].rv=0;
}
}
inline void rotate(ll x)
{
ll fa=nd[x].fa,gfa=nd[fa].fa;
ll dir=nd[fa].ch[1]==x,son=nd[x].ch[!dir];
if(nroot(fa))
{
nd[gfa].ch[nd[gfa].ch[1]==fa]=x;
}
nd[x].ch[!dir]=fa,nd[fa].ch[dir]=son;
if(son)
{
nd[son].fa=fa;
}
nd[fa].fa=x,nd[x].fa=gfa,update(fa);
}
inline void splay(ll x)
{
ll fa=x,gfa,cur=0;
st[++cur]=fa;
while(nroot(fa))
{
st[++cur]=fa=nd[fa].fa;
}
while(cur)
{
spread(st[cur--]);
}
while(nroot(x))
{
fa=nd[x].fa,gfa=nd[fa].fa;
if(nroot(fa))
{
rotate((nd[fa].ch[0]==x)^(nd[gfa].ch[0]==fa)?x:fa);
}
rotate(x);
}
update(x);
}
inline void access(ll x)
{
for(register int i=0;x;x=nd[i=x].fa)
{
splay(x),rs=i,update(x);
}
}
inline void makeRoot(ll x)
{
access(x),splay(x),reverse(x);
}
inline void link(ll edx,ll x,ll y)
{
makeRoot(x);
nd[nd[ex[edx]=x].fa=edx].fa=y,nd[edx].val=dis[x][y],update(edx);
}
inline void cut(ll x)
{
access(ex[x]),splay(x);
ls=rs=nd[ls].fa=nd[rs].fa=0;
}
#undef ls
#undef rs
};
}
LCT::LinkCutTree lct;
int main()
{
n=read(),m=read(),qcnt=read();
for(register int i=1;i<=m;i++)
{
from=ed[i].from=read(),to=ed[i].to=read();
dis[from][to]=dis[to][from]=ed[i].dist=read();
}
for(register int i=1;i<=qcnt;i++)
{
op[i]=read(),x[i]=read(),y[i]=read();
if(op[i]==2)
{
g[x[i]][y[i]]=g[y[i]][x[i]]=1;
}
}
for(register int i=0;i<=n;i++)
{
ffa[i]=i;
}
sort(ed+1,ed+m+1),cnt=n*2-1;
for(register int i=1;cnt>n;i++)
{
from=ed[i].from,to=ed[i].to;
if(!g[from][to]&&find(from)!=find(to))
{
lct.link(cnt--,from,to),ffa[ffa[from]]=ffa[to];
}
}
cnt=0;
for(register int i=qcnt;i;i--)
{
lct.makeRoot(from=x[i]),lct.access(to=y[i]),lct.splay(to);
if(op[i]==1)
{
res[++cnt]=lct.nd[lct.nd[to].mx].val;
}
if(op[i]==2)
{
if(lct.nd[lct.nd[to].mx].val>dis[from][to])
{
lct.cut(xx=lct.nd[to].mx),lct.link(xx,from,to);
}
}
}
while(cnt)
{
printf("%d\n",res[cnt--]);
}
}
Luogu P4172 [WC2006]水管局长的更多相关文章
- luogu P4172 [WC2006]水管局长 LCT维护动态MST + 离线
Code: #include<bits/stdc++.h> #define maxn 1200000 #define N 120000 using namespace std; char ...
- P4172 [WC2006]水管局长
P4172 [WC2006]水管局长 前言 luogu数据太小 去bzoj,他的数据大一些 思路 正着删不好维护 那就倒着加,没了 LCT维护他的最小生成树MST 树上加一条边肯定会有一个环 看看环上 ...
- P4172 [WC2006]水管局长(LCT)
P4172 [WC2006]水管局长 LCT维护最小生成树,边权化点权.类似 P2387 [NOI2014]魔法森林(LCT) 离线存储询问,倒序处理,删边改加边. #include<iostr ...
- 洛谷P4172 [WC2006]水管局长(lct求动态最小生成树)
SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一条从A至B的水管的路径, ...
- P4172 [WC2006]水管局长 LCT维护最小生成树
\(\color{#0066ff}{ 题目描述 }\) SC 省 MY 市有着庞大的地下水管网络,嘟嘟是 MY 市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的 ...
- [洛谷P4172] WC2006 水管局长
问题描述 SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一条从A至B的水 ...
- 洛谷P4172 [WC2006]水管局长 (LCT,最小生成树)
洛谷题目传送门 思路分析 在一个图中,要求路径上最大边边权最小,就不难想到最小生成树.而题目中有删边的操作,那肯定是要动态维护啦.直接上LCT维护边权最小值(可以参考一下蒟蒻的Blog) 这时候令人头 ...
- BZOJ2594: [Wc2006]水管局长数据加强版
题解: 裸LCT+离线+二分+MST... 代码:(几乎摘抄自hzwer) #include<cstdio> #include<cstdlib> #include<cma ...
- bzoj 2594: [Wc2006]水管局长数据加强版 动态树
2594: [Wc2006]水管局长数据加强版 Time Limit: 25 Sec Memory Limit: 128 MBSubmit: 934 Solved: 291[Submit][Sta ...
随机推荐
- 破晓行动----带你总结JVM的知识大全(一)
JVM线程 + JVM内存区域
- RabbitMq如何确保消息不丢失
上篇写了掌握Rabbitmq几个重要概念,从一条消息说起,这篇来总结关于消息丢失让人头痛的事情.网络故障.服务器重启.硬盘损坏等都会导致消息的丢失.消息从生产到消费主要结果以下几个阶段如下图. ①生产 ...
- Java基础——锁
1.锁 当一个共享资源被多方访问时为了避免发生冲突而施加的一种机制 2.乐观锁和悲观锁 Java中锁在宏观分为乐观锁和悲观锁 乐观锁:是一种乐观思想,认为多读少写,一般情况下数据在修改时不会出现冲突, ...
- 用于ASP.net的MVC模块
下载MVCBricks_SRC - 492.58 KB 表的内容 介绍系统要求游戏闪屏的最终考虑历史 介绍 自从我写上一篇关于ASP的文章以来,已经有很长时间了.净的话题.这次我决定写一些关于它的东西 ...
- 如何快速构建React组件库
前言 俗话说:"麻雀虽小,五脏俱全",搭建一个组件库,知之非难,行之不易,涉及到的技术方方面面,犹如海面风平浪静,实则暗礁险滩,处处惊险- 目前团队内已经有较为成熟的 Vue 技术 ...
- Java 合并Word文档
合并文档可以是将两个包含一定逻辑关系的文档合并成一个完整的文档,也可以是出于方便文档存储.管理的目的合并多个文档为一个文档.下面,就将以上文档操作需求,通过Java程序来实现Word文档合并.合并文档 ...
- volatile、ThreadLocal的使用场景和原理
并发编程中的三个概念 原子性 一个或多个操作.要么全部执行完成并且执行过程不会被打断,要么不执行.最常见的例子:i++/i--操作.不是原子性操作,如果不做好同步性就容易造成线程安全问题. 可见性 多 ...
- 2016年 实验五 Internet与网络工具的使用
实验五 Internet与网络工具的使用 [实验目的] 本实验目的在于掌握 Telnet.FTP.Email的工作机理,并会在 Internet 上熟练使用相关工具软件. [实验条件] ⑴.个人计算机 ...
- 霍夫曼编码(Huffman)
题目:有一个字符串:cabcedeacacdeddaaaba,问题: (1)采用霍夫曼编码画出编码的过程,并写出各字符的编码 (2)根据求得的编码,求得各编码需要的总位数 (3)求出整个字符串总编码长 ...
- 程序员,想被别人发掘?那你有 freestyle 吗?
程序员群体是偏内向的,整天和计算机打交道,用代码说话,接受任务,默默工作. 如果这些任务是有挑战性的还行,你的工作成果就能帮你说话,可是大部分工作都是普普通通的,甚至有点儿重复性的劳动. 这个时候表面 ...