BZOJ 2594 水管局长数据加强版(动态树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2594
题意:给出一个无向图,边有权值。定义一条路径的长度为该路径所有边的最大值。两种操作:(1)询问u到v所有路径的长度的最小值;(2)删掉某条边。
思路:
(1)将每个边也转化成一个点,比如边(1,2),转化成(1,3),(3,2)两个边;那么边权看做3的点权;1和2的点权可以看做0;
(2)反着做。首先将删掉的边都删掉,询问倒着回答,那么就成了加边。
(3)显然,路径长度就是最小生成树的最大值。因此,首先,将没有删掉的边求一次最小生成树,将最小生成树的边建立动态树。
(4)对于查询比较简单直接查就行。
(5)对于添加边(u,v),若u与v之前没有连通,则该边直接加进去就行,其实就是两个子树连在一起;否则,该边加进去之后会出现环,那么需要删掉环上的最大值的边。
struct node
{
int Max,maxNode,val,id,isRev;
node *c[2],*f;
void reverse()
{
isRev^=1;
swap(c[0],c[1]);
}
};
node a[N],*nullNode;
void init()
{
nullNode=new node();
nullNode->Max=nullNode->val=nullNode->isRev=0;
nullNode->c[0]=nullNode->c[1]=nullNode->f=nullNode;
}
void pushUp(node *x)
{
if(x==nullNode) return;
x->maxNode=x->id;
x->Max=x->val;
if(x->c[0]!=nullNode&&x->c[0]->Max>x->Max)
{
x->maxNode=x->c[0]->maxNode;
x->Max=x->c[0]->Max;
}
if(x->c[1]!=nullNode&&x->c[1]->Max>x->Max)
{
x->maxNode=x->c[1]->maxNode;
x->Max=x->c[1]->Max;
}
}
void pushDown(node *x)
{
if(x==nullNode) return;
if(x->isRev)
{
if(x->c[0]!=nullNode) x->c[0]->reverse();
if(x->c[1]!=nullNode) x->c[1]->reverse();
x->isRev=0;
}
}
int isRoot(node *x)
{
if(x->f==nullNode) return 1;
node *p=x->f;
return p->c[0]!=x&&p->c[1]!=x;
}
void zig(node *x)
{
node *p=x->f,*q=p->f;
p->c[0]=x->c[1];
if(x->c[1]!=nullNode) x->c[1]->f=p;
x->c[1]=p;
p->f=x;
x->f=q;
if(q!=nullNode)
{
if(q->c[0]==p) q->c[0]=x;
if(q->c[1]==p) q->c[1]=x;
}
pushUp(p);
}
void zag(node *x)
{
node *p=x->f,*q=p->f;
p->c[1]=x->c[0];
if(x->c[0]!=nullNode) x->c[0]->f=p;
x->c[0]=p;
p->f=x;
x->f=q;
if(q!=nullNode)
{
if(q->c[0]==p) q->c[0]=x;
if(q->c[1]==p) q->c[1]=x;
}
pushUp(p);
}
void splay(node *x)
{
pushDown(x);
while(!isRoot(x))
{
if(!isRoot(x->f))
{
pushDown(x->f->f);
pushDown(x->f);
pushDown(x);
if(x->f->f->c[0]==x->f)
{
if(x->f->c[0]==x) zig(x->f),zig(x);
else zag(x),zig(x);
}
else
{
if(x->f->c[1]==x) zag(x->f),zag(x);
else zig(x),zag(x);
}
}
else
{
pushDown(x->f);
pushDown(x);
if(x->f->c[0]==x) zig(x);
else zag(x);
}
}
pushUp(x);
}
node *access(node *x)
{
node *p=nullNode;
while(x!=nullNode)
{
splay(x);
x->c[1]=p;
pushUp(x);
p=x;
x=x->f;
}
return p;
}
void makeRoot(int x)
{
access(a+x);
splay(a+x);
a[x].reverse();
}
void join(int x,int y)
{
makeRoot(x); access(a+y); splay(a+y);
a[x].f=a+y;
}
void cut(int x,int y)
{
makeRoot(x); access(a+y); splay(a+y);
a[y].c[0]->f=nullNode;
a[y].c[0]=nullNode;
splay(a+y);
}
pair<int,int> query(int x,int y)
{
makeRoot(y); access(a+x); splay(a+x);
if(a[y].f==nullNode) return MP(-1,-1);
access(a+x);
node *p=a+y,*q=nullNode;
int Max,maxNode;
while(p!=nullNode)
{
splay(p);
if(p->f==nullNode)
{
Max=p->val;
maxNode=p->id;
if(p->c[1]!=nullNode&&p->c[1]->Max>Max)
{
Max=p->c[1]->Max;
maxNode=p->c[1]->maxNode;
}
if(q!=nullNode&&q->Max>Max)
{
Max=q->Max;
maxNode=q->maxNode;
}
return MP(maxNode,Max);
}
p->c[1]=q;
q=p;
pushUp(q);
p=p->f;
}
}
int W[N];
int n,m,Q;
struct OP
{
int u,v,op,ans;
};
OP b[100005];
int c[N][2];
int get()
{
int x=0;
char c=getchar();
while(c>'9'||c<'0') c=getchar();
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x;
}
struct E
{
int u,v,w,id,flag;
void read()
{
u=get(); v=get(); w=get();
if(u>v) swap(u,v);
flag=1;
}
};
E edge[N];
int cmp(E a,E b)
{
if(a.u!=b.u) return a.u<b.u;
return a.v<b.v;
}
int find(int u,int v)
{
int low=1,high=m,mid;
while(low<=high)
{
mid=(low+high)>>1;
if(edge[mid].u==u&&edge[mid].v==v) return mid;
if(edge[mid].u<u||edge[mid].u==u&&edge[mid].v<v) low=mid+1;
else high=mid-1;
}
}
void Add(int u,int v,int id)
{
pair<int,int> p=query(u,v);
if(p.first!=-1)
{
if(p.second<=W[id]) return;
cut(p.first,c[p.first][0]);
cut(p.first,c[p.first][1]);
}
join(u,id);
join(v,id);
}
int cmp1(E a,E b)
{
return a.w<b.w;
}
int fa[N];
int get(int x)
{
if(fa[x]!=x) fa[x]=get(fa[x]);
return fa[x];
}
vector<int> g[N];
int visit[N];
void BFS(int u)
{
queue<int> Q;
Q.push(u);
int i,v;
while(!Q.empty())
{
u=Q.front();
Q.pop();
visit[u]=1;
FOR0(i,SZ(g[u]))
{
v=g[u][i];
if(a+v==a[u].f) continue;
a[v].f=a+u;
Q.push(v);
}
}
}
void build()
{
sort(edge+1,edge+m+1,cmp1);
int i,u,v,t;
FOR1(i,n+m) fa[i]=i;
FOR1(i,m) if(edge[i].flag)
{
u=get(edge[i].u);
v=get(edge[i].v);
if(u==v) continue;
fa[u]=v;
u=edge[i].u;
v=edge[i].v;
t=edge[i].id;
g[u].pb(t); g[v].pb(t);
g[t].pb(u); g[t].pb(v);
}
FOR1(i,n+m) if(!visit[i]) BFS(i);
sort(edge+1,edge+m+1,cmp);
}
void go()
{
int i;
for(i=Q;i>=1;i--)
{
if(b[i].op==1) b[i].ans=query(b[i].u,b[i].v).second;
else Add(b[i].u,b[i].v,edge[find(b[i].u,b[i].v)].id);
}
FOR1(i,Q) if(b[i].op==1) PR(b[i].ans);
}
int main()
{
n=get(); m=get(); Q=get();
init();
int i,u,v,w,t;
i64 x;
FOR1(i,m)
{
edge[i].read();
edge[i].id=i+n;
c[i+n][0]=edge[i].u;
c[i+n][1]=edge[i].v;
W[n+i]=edge[i].w;
}
sort(edge+1,edge+m+1,cmp);
FOR1(i,Q)
{
b[i].op=get();
b[i].u=get();
b[i].v=get();
if(b[i].u>b[i].v) swap(b[i].u,b[i].v);
if(b[i].op==2)
{
t=find(b[i].u,b[i].v);
edge[t].flag=0;
}
}
for(i=1;i<=n+m;i++)
{
a[i].c[0]=a[i].c[1]=a[i].f=nullNode;
a[i].val=a[i].Max=W[i];
a[i].maxNode=a[i].id=i;
a[i].isRev=0;
}
build();
go();
}
BZOJ 2594 水管局长数据加强版(动态树)的更多相关文章
- bzoj 2594: [Wc2006]水管局长数据加强版 动态树
2594: [Wc2006]水管局长数据加强版 Time Limit: 25 Sec Memory Limit: 128 MBSubmit: 934 Solved: 291[Submit][Sta ...
- [BZOJ]2594 水管局长数据加强版(Wc2006)
失踪人口回归. LCT一直是小C的弱项,特别是这种维护链的信息的,写挂了就会调代码调到心态爆炸. 不过还好这一次的模板练习没有出现太多的意外. Description SC省MY市有着庞大的地下水管网 ...
- bzoj 2594: 水管局长数据加强版 Link-Cut-Tree
题目: Description SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公 ...
- BZOJ 2594 水管局长数据加强版
LCT维护最小生成树 要求两点路径最大的最小,首先想到的肯定是最小生成树,再加上有删边操作,那就得用LCT维护了. 可是对于cut一条边,我们要时刻维护图中的最小生成树,需要把之前被我们淘汰的边找回, ...
- BZOJ 2594: [Wc2006]水管局长数据加强版( LCT )
离线然后就是维护加边的动态MST, Link cut tree秒掉..不过我写+调了好久...时间复杂度O(NlogN + MlogM) ------------------------------- ...
- BZOJ 2594: [Wc2006]水管局长数据加强版 [LCT kruskal]
2594: [Wc2006]水管局长数据加强版 Time Limit: 25 Sec Memory Limit: 128 MBSubmit: 2917 Solved: 918[Submit][St ...
- BZOJ 2594 【WC2006】 水管局长数据加强版
题目链接:水管局长数据加强版 好久没写博客了…… 上次考试的时候写了一发LCT,但是写挂了……突然意识到我已经很久没有写过LCT了,于是今天找了道题来练练手. 首先,LCT这里不讲.这道题要求支持动态 ...
- BZOJ2594: [Wc2006]水管局长数据加强版
题解: 裸LCT+离线+二分+MST... 代码:(几乎摘抄自hzwer) #include<cstdio> #include<cstdlib> #include<cma ...
- [bzoj2594][Wc2006]水管局长数据加强版 (lct)
论蒟蒻的自我修养T_T.. 和noi2014魔法森林基本一样...然而数据范围大得sxbk...UPD:这题如果用lct判联通的话可能会被卡到O(mlogm)..所以最好还是用并查集吧 一开始数组开太 ...
随机推荐
- 如何删除word中多余的空格和空行
去除word中多余的空格及空行 一.去掉表格和格式 为了版面的整齐,网页文档都是以表格的形式存在的,只是一般情况下表格的颜色被设为无色或表格宽度被设为0,所以我们在网页上看不到表格.另外,网 页文档中 ...
- LoadRunner-关联报错(解决方法一)
Action.c(153): Error -35061: No match found for the requested parameter "CorrelationParameter_3 ...
- vue 中 命名视图的用法
今天主要记录 vue中命名视图的用法 先奉上官网网址:https://router.vuejs.org/zh/guide/essentials/named-views.html 一般情况下,一个页面 ...
- 高并发秒杀系统方案(集成Mybatis和Redis)
1.集成Mybatis 第一步,添加依赖: <dependency> <groupId>org.mybatis.spring.boot</groupId> < ...
- idong常用js总结
1.判断屏幕高度 $(document).ready(function() { $("#left").height($(window).height()); $(&qu ...
- UIWebview于JS交互
最近使用火车票网的限行网页,但是广告以及头部nav和地步footer都是我们现在所不需要的,所以决定使用js交互,下面所有代码都写在 webViewDidFinishLoad 里面 1.查看原网址的源 ...
- 使用navicat mysql 远程连接数据库
远程连接数据库,假设两台主机上都有navicat 客户端 远程主机A ip地址:192.168.100.91 ,port 3306,数据库用户名 rootA 密码 123456A 本地主 ...
- SparkSQL UDF使用方法与原理详解
UDF是SQL中很常见的功能,但在Spark-1.6及之前的版本,只能创建临时UDF,不支持创建持久化的UDF,除非修改Spark源码.从Spark-2.0开始,SparkSQL终于支持持久化的UDF ...
- 什么时候block 是放在全局区里面的?
When a Block literal is written where there are global variables When the syntax in a Block literal ...
- window.open和window.showModalDialog
window.open window.open是打开一个新窗口 在window.open打开的窗口中刷新父页面 opener.location.reload(); 打开一个窗口格式:属性可以任意设置 ...