沉迷Link-Cut tree无法自拔之:[BZOJ2594][Wc2006]水管局长数据加强版
来自蒟蒻 \(Hero \_of \_Someone\) 的 \(LCT\) 学习笔记
$
$
这应该算是道套路题吧, 如果将图中的边转换成点, 再将边权变点权, 就可以用 \(LCT\) 来维护了
这道题的基本做法就是, 用 \(LCT\) 来动态地维护最小生成树,
如果这样做的话, 题目中要求的删边操作就不太好搞,
但是既然只有删边操作的话, 我们就可以考虑离线处理,
将不会被删除的边先加进图中跑 \(Kruskal\) , 然后化删边为添边, 倒着来处理每一组询问.
$
$
此外, 用 \(LCT\) 维护 \(MST\) , 就是在添边的时候如果遇到环且环上最长的边边权大于当前边, 就将最大边 \(cut\) , 再将当前边添入
//made by Hero_of_Someone
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define N (100010)
#define M (1000010)
#define RG register
using namespace std;
inline int gi(){ RG int x=0; RG char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar();
while('0'<=ch&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x; }
int n,m,q;
struct Edge{
int u,v,w;
bool operator<(const Edge&a)const{
return u==a.u?v<a.v:u<a.u;
}
bool operator<(const pair<int,int>& a)const{
return u==a.first?v<a.second:u<a.first;
}
}e[M];
struct Que{ int op,x,y; }Q[N];
//-----------------------------------------------------------
int Fa[N];
inline int Find(RG int x){ return Fa[x]==x?x:Fa[x]=Find(Fa[x]); }
struct EEE{
int u,v,w,id;
bool operator<(const EEE& a)const{ return w<a.w; }
void operator=(const Edge& a){
u=a.u,v=a.v,w=a.w,id=(&a)-e;
}
}E[M];
int num,head[N],nxt[N<<1],to[N<<1],w[N<<1]; //w为该边原来的编号
inline void add(int u,int v,int d){
nxt[++num]=head[u];to[num]=v;w[num]=d;head[u]=num;
nxt[++num]=head[v];to[num]=u;w[num]=d;head[v]=num;
}
bool v[M];
inline void kruskal(){
RG int top=0;
for(RG int i=1;i<=n;i++) Fa[i]=i;
for(RG int i=1;i<=m;i++){
if(v[i]) continue;
E[++top]=e[i];
}
sort(E+1,E+top+1);
for(RG int i=1;i<=top;i++){
RG int x=E[i].u,y=E[i].v;
RG int fx=Find(x),fy=Find(y);
if(fx==fy) continue;
Fa[fx]=fy; add(x,y,E[i].id);
}
}
inline void init(){
n=gi(),m=gi(),q=gi();
for(RG int i=1;i<=m;i++){
e[i].u=gi(),e[i].v=gi(),e[i].w=gi();
}
sort(e+1,e+m+1);
for(RG int i=1;i<=q;i++){
Q[i].op=gi(),Q[i].x=gi(),Q[i].y=gi();
if(Q[i].op==2){
RG int V=lower_bound(e+1,e+m+1,make_pair(Q[i].x,Q[i].y))-e;
Q[i].x=V; v[V]=1;
}
}q++;
kruskal();
}
//---------------------------------------------------------------
int val[N+M],Max[N+M];
int ch[N+M][2],fa[N+M],rev[N+M];
inline void cur(int x,int y){ val[x]=Max[x]=y; }
int vis[N];
inline void dfs(RG int x,RG int f,RG int d){
if(vis[x]) return ;
vis[x]=1; cur(x,0);
if(f){ cur(n+d,d); fa[n+d]=f; fa[x]=n+d; } //将边转换成点插入树中
for(RG int i=head[x];i;i=nxt[i])
dfs(to[i],x,w[i]);
}
inline bool cnm(int x,int y){ return e[x].w<e[y].w; }
inline void up(int x){
Max[x]=max(Max[ch[x][0]],Max[ch[x][1]],cnm);
Max[x]=max(Max[x],val[x],cnm);
}
inline void reverse(int x){
swap(ch[x][0],ch[x][1]);
rev[x]^=1;
}
inline void down(int x){
if(!rev[x]) return ;
reverse(ch[x][0]);
reverse(ch[x][1]);
rev[x]=0;
}
inline bool is_root(int x){ return ch[fa[x]][0]!=x && x!=ch[fa[x]][1]; }
inline bool lr(int x){ return x==ch[fa[x]][1]; }
inline void rotate(int x){
RG int y=fa[x],z=fa[y],k=lr(x);
if(!is_root(y)) ch[z][lr(y)]=x;
fa[x]=z; fa[ch[x][k^1]]=y; fa[y]=x;
ch[y][k]=ch[x][k^1]; ch[x][k^1]=y;
up(y); up(x);
}
int st[N+M];
inline void splay(int x){
RG int y=x,top=0;
while(1){
st[++top]=y;
if(is_root(y)) break;
y=fa[y];
}
for(RG int i=top;i;i--) down(st[i]);
while(!is_root(x)){
if(!is_root(fa[x])) rotate(lr(x)^lr(fa[x])?x:fa[x]);
rotate(x);
}
}
inline void access(int x){
RG int y=0;
while(x){ splay(x);
ch[x][1]=y; fa[y]=x;
up(x); y=x; x=fa[x];
}
}
inline void make_root(int x){
access(x); splay(x); reverse(x);
}
inline int query(int x,int y){
make_root(x); access(y); splay(y);
return Max[y];
}
inline int find(int x){
while(fa[x]) x=fa[x];
return x;
}
inline void link(int x,int y){
if(find(x)==find(y)) return ;
make_root(x); fa[x]=y;
}
inline void cut(int x,int y){
make_root(x); access(y); splay(y);
if(ch[y][0]==x) ch[y][0]=0,fa[x]=0,up(y);
}
inline void Insert(int id){
RG int x=e[id].u,y=e[id].v;
if(find(x)==find(y)){
RG int tmp=query(x,y);
if(e[tmp].w<=e[id].w) return ;
cut(n+tmp,e[tmp].u);
cut(n+tmp,e[tmp].v);
}
cur(n+id,id);
link(x,n+id);
link(y,n+id);
}
int Ans[N],top;
inline void work(){
for(RG int i=1;i<=n;i++) dfs(i,0,0);
while(--q){
if(Q[q].op==2) Insert(Q[q].x);
else Ans[++top]=e[query(Q[q].x,Q[q].y)].w;
}
for(RG int i=top;i;i--) printf("%d\n",Ans[i]);
}
int main(){ init(); work(); return 0; }
沉迷Link-Cut tree无法自拔之:[BZOJ2594][Wc2006]水管局长数据加强版的更多相关文章
- BZOJ2594: [Wc2006]水管局长数据加强版
题解: 裸LCT+离线+二分+MST... 代码:(几乎摘抄自hzwer) #include<cstdio> #include<cstdlib> #include<cma ...
- [bzoj2594][Wc2006]水管局长数据加强版 (lct)
论蒟蒻的自我修养T_T.. 和noi2014魔法森林基本一样...然而数据范围大得sxbk...UPD:这题如果用lct判联通的话可能会被卡到O(mlogm)..所以最好还是用并查集吧 一开始数组开太 ...
- BZOJ2594 [Wc2006]水管局长数据加强版 【LCT维护最小生成树】
题目 SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一条从A至B的水管的 ...
- BZOJ2594 [Wc2006]水管局长数据加强版 LCT kruskal
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2594 题意概括 N个点的图,M条带权边.(N<=100000,M<=1000000) ...
- [bzoj2594][Wc2006]水管局长数据加强版——lct+离线
Brief Description 您有一个无向带权图,您需要支持两种操作. 询问两个点之间的最大权最小路径. 删除一条边. Algorithm Design 我们首先提出一个猜想:最优路径一定在原图 ...
- bzoj2594 [Wc2006]水管局长数据加强版——LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2594 时间倒序一下,就是 魔法森林 那道题: 有个不解的地方,是 access 里面关于 p ...
- [BZOJ2594] [Wc2006]水管局长数据加强版(LCT + kruskal + 离线)
传送门 WC这个题真是丧心病狂啊,就是想学习一下怎么处理边权,给我来了这么一个破题! ORZ hzwer 临摹黄学长代码233 但还是复杂的一匹 理一下思路吧 题目大意:给定一个无向图,多次删除图中的 ...
- 【bzoj2594】 Wc2006—水管局长数据加强版
http://www.lydsy.com/JudgeOnline/problem.php?id=2594 (题目链接) 题意 给出一个带边权的无向简单,要求维护两个操作,删除${u,v}$之间的连边: ...
- 【bzoj2594】[Wc2006]水管局长数据加强版
真是神题 当时调了几天没调出来 后来没管了 当时把fread去掉就TLE,加上就RE 一直在底下跟网上的程序拍,尝试各种优化常数都没用 拍出几组不一样的,发现我是对的,醉了,网上那个是怎么过的 记一下 ...
随机推荐
- Docker 快速验证 HTML 导出 PDF 高效方案
需求分析 项目中用到了 Echarts,想要把图文混排,当然包括 echarts 生成的 Canvas 图也导出 PDF. 设计和实现时,分析了 POI.iText.freemaker.world 的 ...
- 支持自定义协议的虚拟仪器【winform版】
首先,这个程序的由来,额,工作以来,做的最久的就是上位机,对市面上的大部分组态软件都感到不满,不好用,LabView虽然用起来不错,但是入门还是不够简单,刚好现在工作比较闲(已经不再做上位机了),所以 ...
- c++ 中关于一些变量不能声明的问题
j0,j1,jn,y0,y1,yn被c++中某些函数占用了,所以是不能被声明的,今天就遇到了这个问题,结果我在自己写的程序中找了半天都没找到重复申明的y1
- 12.17 Daily Scrum
Today's Task Tomorrow's Task 丁辛 实现和菜谱相关的餐厅列表. 实现和菜谱相关的餐厅列表. 邓亚梅 美化搜索框UI. 美 ...
- 20135327郭皓--Linux内核分析第七周 可执行程序的装载
第七周 可执行程序的装载 郭皓 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 ...
- kNN算法学习(一)
1.首先需要一些训练样本集,例如一道问题(数据)及答案(标签),可以看做一条样本,那么多条,就是样本集 当然这里应该是一条数据及该数据所属的分类,该类别称为标签 2.现在我们已经知道数据与所属类别的对 ...
- HanderBar
对于java开发,涉及到页面展示时,比较主流的有两种解决方案: 1. struts2+vo+el表达式. 这种方式,重点不在于struts2,而是vo和el表达式,其基本思想是:根据页面需要的信息,构 ...
- 构建之法--初识Git
该作业来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2103 GitHub地址:https://github.com/GVic ...
- 使用YII框架的migrate迁移数据库
框架版本:2.0.13 官网手册说明:http://www.yiichina.com/doc/guide/2.0/db-migrations 创建迁移 命令的格式: php yii migrate/c ...
- TimeLine CSS/Javascript 时间线
https://casbootadminserver.herokuapp.com/#/applications/23bd8218/trace