题意

给定一个 \(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]水管局长的更多相关文章

  1. luogu P4172 [WC2006]水管局长 LCT维护动态MST + 离线

    Code: #include<bits/stdc++.h> #define maxn 1200000 #define N 120000 using namespace std; char ...

  2. P4172 [WC2006]水管局长

    P4172 [WC2006]水管局长 前言 luogu数据太小 去bzoj,他的数据大一些 思路 正着删不好维护 那就倒着加,没了 LCT维护他的最小生成树MST 树上加一条边肯定会有一个环 看看环上 ...

  3. P4172 [WC2006]水管局长(LCT)

    P4172 [WC2006]水管局长 LCT维护最小生成树,边权化点权.类似 P2387 [NOI2014]魔法森林(LCT) 离线存储询问,倒序处理,删边改加边. #include<iostr ...

  4. 洛谷P4172 [WC2006]水管局长(lct求动态最小生成树)

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

  5. P4172 [WC2006]水管局长 LCT维护最小生成树

    \(\color{#0066ff}{ 题目描述 }\) SC 省 MY 市有着庞大的地下水管网络,嘟嘟是 MY 市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的 ...

  6. [洛谷P4172] WC2006 水管局长

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

  7. 洛谷P4172 [WC2006]水管局长 (LCT,最小生成树)

    洛谷题目传送门 思路分析 在一个图中,要求路径上最大边边权最小,就不难想到最小生成树.而题目中有删边的操作,那肯定是要动态维护啦.直接上LCT维护边权最小值(可以参考一下蒟蒻的Blog) 这时候令人头 ...

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

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

  9. bzoj 2594: [Wc2006]水管局长数据加强版 动态树

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

随机推荐

  1. Python-对字典进行排序

    案例: 某班英语成绩以字典的形式存储为: {'lili':78, 'jin':50, 'liming': 30, ......} 依据成绩高低,进行学生成绩排名 如何对字典排序? 方法1: #!/us ...

  2. c++ 中预编译头文件名 pch.h

    转载:https://www.it-swarm.asia/zh/c++/%e6%88%91%e5%8f%af%e4%bb%a5%e4%bd%bf%e7%94%a8includepchh%e2%80%9 ...

  3. JDBC Java 连接 MySQL 数据库

    MySQL 版本:Server version: 5.7.17-log MySQL Community Server (GPL) 用于测试的 MySQL 数据库:game 查看数据库中的表 mysql ...

  4. sqlserver 分列

    sql server 数据库中某张表(Person)的数据信息是: ID Address 1 平山花园-4单元-12幢-203 2 香山花园-3单元-22幢-304 现在有需求是,将地址信息显示形式改 ...

  5. Solon集成(02)- 轻松吃下小馒头 Dubbo

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  6. Python 3.9 新特性速览

    国庆假期,Python 社区发布了 3.9 版本的第一个 stable release. 相比于 3.8,Python 3.9 新特性众多,但不少特性与大多数 Python"使用者" ...

  7. Azure Cosmos DB (二) SQL API 操作

    一,引言 还记得国庆期间,我们学习了一下关于Azure Cosmos DB 的一些基础知识以及Azure Cosmos DB 的几种支持数据库类型.今天就开始分享一些实战操作,如何通过Azure Po ...

  8. Windows7 提示“无法访问您可能没有权限使用网络资源”的解决办法

    大家经常会碰到,电脑A(Windows7)访问局域网打印机的时候出现提示"无法访问你可能没有权限使用网络资源",导致无法正常使用打印机. 那么出现这种情况该如何解决呢? 解决方法: ...

  9. 营口6378.7939(薇)xiaojie:营口哪里有xiaomei

    营口哪里有小姐服务大保健[微信:6378.7939倩儿小妹[营口叫小姐服务√o服务微信:6378.7939倩儿小妹[营口叫小姐服务][十微信:6378.7939倩儿小妹][营口叫小姐包夜服务][十微信 ...

  10. 洛谷 CF1012C Hills(动态规划)

    题目大意: 有几座山,如果一座山左右两边的山比它矮,那么可以在这个山上建房子,你有一台挖掘机,每天可以挖一座山一米,问你需要花多少代价可以分别盖1.2.3--座房子.(给出山的数量,以及每座山的高度) ...