CF487E Tourists

一般图,带修求所有简单路径代价。

简单路径,不能经过同一个点两次,那么每个V-DCC出去就不能再回来了。

所以可以圆方树,然后方点维护一下V-DCC内的最小值。

那么,从任意一个割点进入这个DCC,必然可以绕一圈再从另一个割点出去。

所以,路径上的最小值,就是圆方树路径上的最小值。方点的最小值就是在这个DCC中走一走得到的。

树链剖分+线段树维护路径

用堆维护方点四周的圆点的最小值。然后更新。

一个问题是:

更新一个割点圆点,会影响到四周所有的方点。暴力更新,菊花图直接TLE

这样更新:

方点只维护圆方树上儿子圆点的最值。

这样,每次修改圆点,只要修改father的方点的值即可。

查询路径的时候,如果LCA是方点,那么把这个方点的father的值也取min即可。

圆点就无所谓了。LCA自己一定会取到的。

代码:

#include<bits/stdc++.h>
#define reg register int
#define mid ((l+r)>>1)
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=2e5+;
const int inf=0x3f3f3f3f;
int n,m,q;
struct node{
int nxt,to;
}e[*N],bian[*N];
int hd[N],pre[N];
int cnt1,cnt2;
void _add(int x,int y){
bian[++cnt1].nxt=pre[x];
bian[cnt1].to=y;
pre[x]=cnt1;
}
void add(int x,int y){
e[++cnt2].nxt=hd[x];
e[cnt2].to=y;
hd[x]=cnt2;
}
struct heap{
priority_queue<int,vector<int>,greater<int> >h,d;
int top(){
while(h.size()&&d.size()&&h.top()==d.top()){
h.pop();d.pop();
}
if(h.empty()) return inf;
return h.top();
}
void push(int c){
h.push(c);
}
void dele(int c){
d.push(c);
}
}f[N];
int w[N];
int tot,df;
int dfn[N],low[N],sta[N],tp;
void tarjan(int x){
dfn[x]=low[x]=++df;
sta[++tp]=x;
for(reg i=pre[x];i;i=bian[i].nxt){
int y=bian[i].to;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(dfn[x]<=low[y]){
++tot;//fang
w[tot]=inf;//warning!!!
int z;
do{
z=sta[tp--];
add(tot,z);add(z,tot);
}while(z!=y);
add(x,tot);add(tot,x);
}
}
else low[x]=min(low[x],dfn[y]);
}
}
int dep[N],fa[N],top[N],fdfn[N],son[N],sz[N];
void dfs1(int x,int d){
dep[x]=d;
sz[x]=;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa[x]) continue;
fa[y]=x;
dfs1(y,d+);
sz[x]+=sz[y];
if(sz[y]>sz[son[x]]) son[x]=y;
if(x>n){//a fang
f[x].push(w[y]);
w[x]=min(w[x],w[y]);
}
}
}
void dfs2(int x){
dfn[x]=++df;
fdfn[df]=x;
if(!top[x]) top[x]=x;
if(son[x]) top[son[x]]=top[x],dfs2(son[x]);
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa[x]) continue;
if(y==son[x]) continue;
dfs2(y);
}
}
int mi[*N];
void pushup(int x){
mi[x]=min(mi[x<<],mi[x<<|]);
}
void build(int x,int l,int r){
if(l==r){
mi[x]=w[fdfn[l]];return;
}
build(x<<,l,mid);
build(x<<|,mid+,r);
pushup(x);
}
void chan(int x,int l,int r,int to,int c){
if(l==r){
mi[x]=c;return;
}
if(to<=mid) chan(x<<,l,mid,to,c);
else chan(x<<|,mid+,r,to,c);
pushup(x);
}
int query(int x,int l,int r,int L,int R){
if(L<=l&&r<=R){
return mi[x];
}
int ret=inf;
if(L<=mid) ret=min(ret,query(x<<,l,mid,L,R));
if(mid<R) ret=min(ret,query(x<<|,mid+,r,L,R));
return ret;
}
int wrk(int x,int y){
int ret=inf;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ret=min(ret,query(,,tot,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
ret=min(ret,query(,,tot,dfn[y],dfn[x]));
if(y>n) ret=min(ret,w[fa[y]]);
return ret;
}
int main(){
rd(n);rd(m);rd(q);
for(reg i=;i<=n;++i)rd(w[i]);
int x,y;
for(reg i=;i<=m;++i){
rd(x);rd(y);
_add(x,y);_add(y,x);
}
tot=n;
tarjan();
memset(dfn,,sizeof dfn);
df=;
dfs1(,);
dfs2();
build(,,tot);
char ch[];
while(q--){
scanf("%s",ch+);
if(ch[]=='A'){
rd(x);rd(y);
printf("%d\n",wrk(x,y));
}
else{
rd(x);rd(y);
int ff=fa[x];
f[ff].dele(w[x]);
f[ff].push(y);
int tmp=f[ff].top();
chan(,,tot,dfn[ff],tmp);
w[ff]=tmp;//no use in fact
w[x]=y;
chan(,,tot,dfn[x],y);
}
}
return ;
} }
int main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/11/30 16:10:40
*/

Tourists——圆方树的更多相关文章

  1. CF487E Tourists(圆方树+树链剖分+multiset/可删堆)

    CF487E Tourists(圆方树+树链剖分+multiset/可删堆) Luogu 给出一个带点权的无向图,两种操作: 1.修改某点点权. 2.询问x到y之间简单路径能走过的点的最小点权. 题解 ...

  2. CF487E Tourists 圆方树、树链剖分

    传送门 注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点 注意:这里不能缩边双联通分量,样例\(2\)就 ...

  3. CF487E Tourists[圆方树+树剖(线段树套set)]

    做这题的时候有点怂..基本已经想到正解了..结果感觉做法有点假,还是看了正解题解.. 首先提到简单路径上经过的点,就想到了一个关于点双的结论:两点间简单路径上所有可能经过的点的并等于路径上所有点所在点 ...

  4. uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)

    - 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...

  5. CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)

    QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...

  6. 【CF487E】Tourists(圆方树)

    [CF487E]Tourists(圆方树) 题面 UOJ 题解 首先我们不考虑修改,再来想想这道题目. 我们既然要求的是最小值,那么,在经过一个点双的时候,走的一定是具有较小权值的那一侧. 所以说,我 ...

  7. 【学习笔记】圆方树(CF487E Tourists)

    终于学了圆方树啦~\(≧▽≦)/~ 感谢y_immortal学长的博客和帮助 把他的博客挂在这里~ 点我传送到巨佬的博客QwQ! 首先我们来介绍一下圆方树能干什么呢qwq 1.将图上问题简化到树上问题 ...

  8. 圆方树简介(UOJ30:CF Round #278 Tourists)

    我写这篇博客的原因 证明我也是学过圆方树的 顺便存存代码 前置技能 双联通分量:点双 然后就没辣 圆方树 建立 新建一个图 定义原图中的所有点为圆点 对于每个点双联通分量(只有两个点的也算) 建立一个 ...

  9. Codeforces 487E Tourists [广义圆方树,树链剖分,线段树]

    洛谷 Codeforces 思路 首先要莫名其妙地想到圆方树. 建起圆方树后,令方点的权值是双联通分量中的最小值,那么\((u,v)\)的答案就是路径\((u,v)\)上的最小值. 然而这题还有修改, ...

随机推荐

  1. php 操作RabbitMQ

    本文摘抄自:https://www.cnblogs.com/alin-qu/p/8312874.html php 操作RabbitMQ   基本流程图 如果exchange 没有绑定queue,则消息 ...

  2. JavaSE 第二次学习随笔(关于内存的小题)

    class HelloA { public HelloA() { System.out.println("HelloA"); } { System.out.println(&quo ...

  3. 人人都会设计模式:观察者模式--Observer

    https://segmentfault.com/a/1190000012295887 观察者模式是抽像通知者和观察者,达到具体通知者跟具体观察者没有偶合.能达到不管是切换通知者,或者是切换观察者,都 ...

  4. python2.7入门---异常处理

        python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误.我们可以使用该功能来调试python程序. 异常处理. 断言(Assertions).     首先来看py ...

  5. [【转】ubuntu 16.10 Server 安装及基本部署

    一.Ubuntu Server 16.10 LTS 系统安装 Ubuntu 16.10 分为 桌面版 (desktop)和服务器版(Server).两者对于用户而言,最大的区别在于桌面版有图形操作界面 ...

  6. Uber:中国市场两年内不考虑盈利,每年补贴10亿美金

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  7. 怎样安装PyCharm

    在地址栏输入http://www.jetbrains.com/pycharm/ 打开PyCharm官网 http://idea.lanyus.com/

  8. centos7源码安装cloud-init

    <template> <name>centos72-source</name> <os> <name>CentOS-7</name&g ...

  9. HDFS分布式集群

    一.HDFS伪分布式环境搭建 Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时, ...

  10. 图解Transformer

    图解Transformer 前言 Attention这种机制最开始应用于机器翻译的任务中,并且取得了巨大的成就,因而在最近的深度学习模型中受到了大量的关注.在在这个基础上,我们提出一种完全基于Atte ...