【题意】给定带边权仙人掌图,Q次询问两点间最短距离。n,m,Q<=10000

【算法】圆方树处理仙人掌问题

【题解】树上的两点间最短路问题,常用倍增求LCA解决,考虑扩展到仙人掌图。

先对仙人掌图建圆方树,圆圆边和原图边权一致。对于每个方点代表的环,记深度最小的点为x,则圆方边的边权是圆点到x的最短距离。

若lca(u,v)为圆点,则两点间最短路转化为圆方树上dis[u]+dis[v]-2*dis[lca]。(向上延伸的路径,经过环则必然经过每个方点的x,计算无误)

若lca(u,v)为方点,则记u,v在方点连接的圆点A,B的子树内,那么两点间最短路为dis[u]+dis[v]-dis[A]-dis[B]+dis(A,B),dis(A,B)是A,B在环上的短侧路径。

复杂度O(Q log n)。

实现细节:

1.Tarjan:建圆方树(先处理树边,最后在深度最小处处理环)

2.处理方点:s[i]表示点i从所在环点x(深度最小)开始逆时针的距离,最终s[x]记为s[N]后s[x]=0。另外注意要记录一下环中点的编号顺序。

3.LCA:圆点直接计算,方点中dis(A,B)=min{ s[A]+s[w]-s[B] , s[B]-s[A] }(A在B的顺时针方向,否则交换AB)。

4.注意防止访问父亲的边是i^1,初始tot=1。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=;
int N,fa[maxn],b[maxn],f[maxn][],dfn[maxn],low[maxn],dfsnum=,deep[maxn],A,B,n,m,id[maxn];
ll s[maxn],dis[maxn];
struct tu{
int first[maxn],tot;
struct edge{int v,w,from;}e[maxn*];
void insert(int u,int v,int w){
tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;
tot++;e[tot].v=u;e[tot].w=w;e[tot].from=first[v];first[v]=tot;
}
}G;
int first[maxn],tot;
struct edge{int v,w,from;}e[maxn*];
void insert(int u,int v,int w){
tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;
tot++;e[tot].v=u;e[tot].w=w;e[tot].from=first[v];first[v]=tot;
}
void solve(int u,int v,int w){
N++;
int pre=w,ID=;
for(int i=v;i!=fa[u];i=fa[i]){
s[i]=pre;
pre+=b[i];
id[i]=ID++;
}
s[N]=s[u];s[u]=;
for(int i=v;i!=fa[u];i=fa[i])insert(N,i,min(s[i],s[N]-s[i]));
}
void tarjan(int x,int father){
dfn[x]=low[x]=++dfsnum;
for(int i=G.first[x];i;i=G.e[i].from)if(i!=father){
int y=G.e[i].v;
if(!dfn[y]){
fa[y]=x;b[y]=G.e[i].w;
tarjan(G.e[i].v,i^);
low[x]=min(low[x],low[y]);
}else low[x]=min(low[x],dfn[y]);
if(low[y]>dfn[x])insert(x,y,G.e[i].w);
}
for(int i=G.first[x];i;i=G.e[i].from){
int y=G.e[i].v;
if(fa[y]!=x&&dfn[y]>dfn[x])solve(x,y,G.e[i].w);
}
}
void dfs(int x,int father){
for(int j=;(<<j)<=deep[x];j++)f[x][j]=f[f[x][j-]][j-];
for(int i=first[x];i;i=e[i].from)if(i!=father){
f[e[i].v][]=x;
deep[e[i].v]=deep[x]+;
dis[e[i].v]=dis[x]+e[i].w;
dfs(e[i].v,i^);
}
}
int lca(int x,int y){
if(deep[x]<deep[y])swap(x,y);
int d=deep[x]-deep[y];
for(int i=;(<<i)<=d;i++)if(d&(<<i))x=f[x][i];
if(x==y)return x;
for(int i=;i>=;i--)if((<<i)<=deep[x]&&f[x][i]!=f[y][i]){
x=f[x][i];y=f[y][i];
}
A=x;B=y;
return f[x][];
} int main(){
int Q;
scanf("%d%d%d",&n,&m,&Q);
int u,v,w;
G.tot=;tot=;
for(int i=;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
G.insert(u,v,w);
}
N=n;tarjan(,);dfs(,);
while(Q--){
scanf("%d%d",&u,&v);
w=lca(u,v);
if(w<=n)printf("%lld\n",dis[u]+dis[v]-*dis[w]);
else{
ll ans=dis[u]+dis[v]-dis[A]-dis[B];
if(id[A]<id[B])ans+=min(s[A]+s[w]-s[B],s[B]-s[A]);
else ans+=min(s[B]+s[w]-s[A],s[A]-s[B]);
printf("%lld\n",ans);
}
}
return ;
}

【BZOJ】2125: 最短路 圆方树(静态仙人掌)的更多相关文章

  1. 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)

    orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...

  2. BZOJ2125 最短路 圆方树、倍增

    传送门 对仙人掌建立圆方树,然后对边定权 对于圆点和圆点之间的边,是原来仙人掌上的桥,边权保持不变 对于圆点和方点之间的边,将圆方树看做以一个圆点为根的有根树之后,一个方点的父亲一定是一个圆点.对于这 ...

  3. [BZOJ2125]最短路(圆方树DP)

    题意:仙人掌图最短路. 算法:圆方树DP,$O(n\log n+Q\log n)$ 首先建出仙人掌圆方树(与点双圆方树的区别在于直接连割边,也就是存在圆圆边),然后考虑点u-v的最短路径,显然就是:在 ...

  4. [BZOJ2125]最短路[圆方树]

    题意 给定仙人掌,多次询问两点之间的最短路径. \(n\le 10000, Q\le 10000​\) 分析 建出圆方树,分路径 lca 是圆点还是方点讨论. 预处理出根圆点到每个圆点的最短距离 \( ...

  5. 圆方树总结 [uoj30]Tourists

    圆方树总结 所谓圆方树就是把一张图变成一棵树. 怎么变啊qaq 这里盗一张图 简单来说就是给每一个点双新建一个点,然后连向这个点双中的每一个点.特殊的,把两个点互相连通的也视作一个点双. 我们把原来就 ...

  6. bzoj 2125 最短路 点双 圆方树

    LINK:最短路 一张仙人掌图 求图中两点最短路. \(n<=10000,Q<=10000,w>=1\) 考虑边数是多少 m>=n-1 对于一张仙人掌图 考虑先构建出来dfs树 ...

  7. BZOJ.2125.最短路(仙人掌 圆方树)

    题目链接 圆方树.做题思路不写了.. 就是当LCA是方点时跳进那个环可以分类讨论一下用树剖而不必须用倍增: 如果v是u的(唯一的那个)重儿子,那么u的DFS序上+1的点即是要找的:否则v会引出一条新的 ...

  8. 【BZOJ2125】最短路(仙人掌,圆方树)

    [BZOJ2125]最短路(仙人掌,圆方树) 题面 BZOJ 求仙人掌上两点间的最短路 题解 终于要构建圆方树啦 首先构建出圆方树,因为是仙人掌,和一般图可以稍微的不一样 直接\(tarjan\)缩点 ...

  9. 2018.07.25 bzoj2125: 最短路(圆方树+倍增)

    传送门 人生的第一道仙人掌. 这道题求是仙人掌上的最短路. 先建出圆方树,然后用倍增跑最短路,当lca" role="presentation" style=" ...

随机推荐

  1. Windows Forms编程实战学习:第三章 菜单

    第三章 菜单 1,控件和容器 所有的Windows Forms控件都是从System.Windows.Forms.Control类继承的,相关类的层次结构如下图所示: MarshalByRefObje ...

  2. HTTPD解析介绍

    配置文件全局介绍 (1)主配置文件:/etc/httpd/conf/httpd.conf 全局配置:Section 1: Global Environment 第33行 中心主机配置: Section ...

  3. (五)Jmeter中的属性和变量

    一.Jmeter中的属性: 1.JMeter属性统一定义在jmeter.properties文件中,我们可以在该文件中添加自定义的属性 2.JMeter属性在测试脚本的任何地方都是可见的(全局),通常 ...

  4. 利用Docker安装Web前端性能测试工具Sitespeed.io

    目录结构 一.Sitespeed.io概述 1.Sitespeed.io简介 2.Sitespeed.io使用场景 二.Sitespeed.io的安装和使用 1.安装Sitespeed.io 2.连接 ...

  5. win7仿win98电脑主题

    http://ys-d.ys168.com/599631823/S7hMfgo3M382J764IOJ8/plus98_for_windows_7_by_ansonsterling.zip

  6. ADO之command

    connection      command对象使用的数据库连接 commandText     执行的SQL语句 ExecuteNonQuery  执行不返回行的语句,如UPDATE等 Execu ...

  7. Java容器深入浅出之List、ListIterator和ArrayList

    List是Collection接口的子接口,表示的是一种有序的.可重复元素的集合. List接口的主要实现类ArrayList和Vector,底层都是维护了一套动态的,可扩展长度的Object[]数组 ...

  8. C#使用 SharpSSH

    准备试一把监控Linux机器 . 附件如下 :http://files.cnblogs.com/files/lclblog/Tamir.SharpSsh.zip

  9. P3386 【模板】二分图匹配

    题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正整数u,v,表示u,v有一条连边 ...

  10. [AT2364] [agc012_d] Colorful Balls

    题目链接 AtCoder:https://agc012.contest.atcoder.jp/tasks/agc012_d 洛谷:https://www.luogu.org/problemnew/sh ...