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. YII2.0 表单验证手机号是否合法且唯一

    [['phone'], 'unique'], ['phone','match','pattern'=>'/^1[345678]{1}\d{9}$/','message'=>'{attrib ...

  2. Python接受流式输入

    随笔记录——Python接受终端入若干行输入 Python接受终端的若干行输入时,比较常用的input()不再好用. 1. 导入sys模块: import sys 2. for循环接受输入: for ...

  3. PAT-B1032

    1032 挖掘机技术哪家强(20) 输入格式: 输入在第1行给出不超过10^5^的正整数N,即参赛人数.随后N行,每行给出一位参赛者的信息和成绩,包括其所代表的学校的编号(从1开始连续编号).及其比赛 ...

  4. 【Leetcode】605. Can Place Flowers

    Description Suppose you have a long flowerbed in which some of the plots are planted and some are no ...

  5. python基础之socket套接字基础part2

    基于UDP的socket 面向无连接的不可靠数据传输,可以没有服务器端,只不过没有服务器端,发送的数据会被直接丢弃,并不能到达服务器端 1 #客户端 2 import socket 3 ip_port ...

  6. linux挂载命令mount及U盘、移动硬盘的挂载

    一.mount的命令格式是(注意mount只能在root权限下运行) mount dervice dir dervice是要挂载的设备,dir是挂载点 二.查看当前磁盘列表的设备 fdisk -l 显 ...

  7. A problem occurred evaluating project ':'. > ASCII

    项目编译出错: 错误信息如下: FAILURE: Build failed with an exception. * Where: Build file 'F:\git\i***\build.grad ...

  8. Office使用技巧(不断补充)

    1.word中,第一行后面有很多空格,但把第二行的退到第一行来就删了第一行的字,为什么? 解决办法:应该是下一行开头部分是一个不可拆分的整体,上一行末尾放不下,只能放在下一行.处理方法:格式--段落- ...

  9. 活动的生命周期 Android

    1.运行程序 onCreate().onStart()和 onResume() 2.跳转到非弹框视图控制器 onPause()和 onStop() 返回上一个视图控制器(没被回收) onRestart ...

  10. Android Open Source Projects(汇总与整理)

    Android Open Source Projects 目前包括: Android开源项目第一篇——个性化控件(View)篇  包括ListView.ActionBar.Menu.ViewPager ...