Description

给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。

Input

输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一条无向边v-u,长度为w 最后Q行,每行两个整数v,u表示一组询问

Output

输出Q行,每行一个整数表示询问的答案

Sample Input

9 10 2
1 2 1
1 4 1
3 4 1
2 3 1
3 7 1
7 8 2
7 9 2
1 5 3
1 6 4
5 6 1
1 9
5 7

Sample Output

5
6

HINT

对于100%的数据,N<=10000,Q<=10000

正解:仙人掌+圆方树。

这道题直接判环好像很不好写的样子。。于是我去学了圆方树。

圆方树其实就是边双连通分量缩点。。把一个环上的点全部连到一个新点上,把这个点称作方点,其他点都是圆点。

不是环上的边就直接按照原图连就行了。

然后我们可以发现,这样得到的树和原来的仙人掌其实是等价的。

参见神犇博客:http://www.cnblogs.com/zzqsblog/p/5851393.html

蒯两个图:

仙人掌:

圆方树:

如何给这棵树设边权?如果是两个圆点之间的边,那么边权就是原边权,如果是圆方点之间的边,那么边权就是圆点到那个环顶的最短路径。

如何查询两点间最短路径?首先我们发现,如果两点的$LCA$是圆点,那么最短路就是两点之间距离,否则就要特判一下$LCA$的那两个儿子在环上的最短距离。

于是我们就能成功地解决仙人掌最短路问题了。

150行。。写得我要爽死了。。

 //It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define N (40010)
#define il inline
#define RG register
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; int n,m,q; struct edge{ int nt,to,dis; }; struct YFtree{ edge g[*N]; int head[N],top[N],fa[N],son[N],dep[N],tid[N],pos[N],sz[N],dis[N],D[N],fg[N],nn,num,cnt; il void insert(RG int from,RG int to,RG int dis){
g[++num]=(edge){head[from],to,dis},head[from]=num; swap(from,to);
g[++num]=(edge){head[from],to,dis},head[from]=num; return;
} il void dfs1(RG int x,RG int p){
fa[x]=p,dep[x]=dep[p]+,sz[x]=; RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
dis[v]=dis[x]+g[i].dis;
dfs1(v,x),sz[x]+=sz[v];
if (sz[son[x]]<=sz[v]) son[x]=v;
}
return;
} il void dfs2(RG int x,RG int p,RG int anc){
top[x]=anc,tid[x]=++cnt,pos[cnt]=x;
if (son[x]) dfs2(son[x],x,anc); RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p || v==son[x]) continue;
dfs2(v,x,v);
}
return;
} il int lca(RG int u,RG int v){
while (top[u]!=top[v]){
if (dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v] ? u : v;
} il int jump(RG int u,RG int Lca){
RG int last;
while (top[u]!=top[Lca])
last=top[u],u=fa[top[u]];
return u==Lca ? last : pos[tid[Lca]+];
} il int query(RG int u,RG int v){
RG int Lca=lca(u,v);
if (Lca<=n) return dis[u]+dis[v]-*dis[Lca];
RG int uu=jump(u,Lca),vv=jump(v,Lca);
RG int du=dis[uu]-dis[Lca],dv=dis[vv]-dis[Lca];
if (!fg[uu]) du=D[Lca]-du; if (!fg[vv]) dv=D[Lca]-dv;
if (du>dv) swap(du,dv);
return dis[u]-dis[uu]+dis[v]-dis[vv]+min(dv-du,D[Lca]-(dv-du));
} }YF; struct Graph{ edge g[*N]; int head[N],fa[N],dep[N],dis[N],dfn[N],low[N],st[N],num,cnt; il void insert(RG int from,RG int to,RG int dis){
g[++num]=(edge){head[from],to,dis},head[from]=num; return;
} il void dfs(RG int x,RG int p){
fa[x]=p,dep[x]=dep[p]+,dfn[x]=low[x]=++cnt; RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
if (!dfn[v]){
dis[v]=dis[x]+g[i].dis,dfs(v,x);
low[x]=min(low[x],low[v]);
} else low[x]=min(low[x],dfn[v]);
if (dfn[x]<low[v]) YF.insert(x,v,g[i].dis);
}
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
if (fa[v]!=x && dfn[x]<dfn[v]) build(x,v,g[i].dis);
}
return;
} il void build(RG int rt,RG int x,RG int d){
RG int top=dep[x]-dep[rt]+,tot=d,Dis=;
for (RG int i=x;i!=rt;i=fa[i])
st[top--]=i,tot+=dis[i]-dis[fa[i]];
YF.D[++YF.nn]=tot,st[]=rt,top=dep[x]-dep[rt]+;
for (RG int i=;i<=top;++i){
RG int dd=min(Dis,tot-Dis);
YF.fg[st[i]]=dd==Dis;
YF.insert(YF.nn,st[i],dd);
Dis+=dis[st[i+]]-dis[st[i]];
}
return;
} }G; il int gi(){
RG int x=,q=; RG char ch=getchar();
while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar();
while (ch>='' && ch<='') x=x*+ch-,ch=getchar(); return q*x;
} il void work(){
n=gi(),m=gi(),q=gi(); YF.nn=n;
for (RG int i=,u,v,w;i<=m;++i){
u=gi(),v=gi(),w=gi();
G.insert(u,v,w),G.insert(v,u,w);
}
G.dfs(,); YF.dfs1(,); YF.dfs2(,,);
for (RG int i=,u,v;i<=q;++i){
u=gi(),v=gi();
printf("%d\n",YF.query(u,v));
}
return;
} int main(){
File("shortest");
work();
return ;
}

bzoj2125 最短路的更多相关文章

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

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

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

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

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

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

  4. BZOJ2125 最短路 【仙人掌最短路】

    题目 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. 输入格式 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一 ...

  5. bzoj2125 最短路——仙人掌两点间距离

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2125 仙人掌!模仿 lyd 的代码写的,也算是努力理解了: 主要分成 lca 在环上和不在环 ...

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

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

  7. 【题解】Bzoj2125最短路

    处理仙人掌 ---> 首先建立出圆方树.则如果询问的两点 \(lca\) 为圆点,直接计算即可, 若 \(lca\) 为方点,则需要额外判断是走环的哪一侧(此时与两个点在环上的相对位置有关.) ...

  8. bzoj3047:Freda的传呼机&&bzoj2125: 最短路

    完结撒花!!!!!!!!!!! 最后一题填坑1A仙人掌WWWWWWW我真流弊 首先把环拆开,环中每一个点连向环的根,然后搞LCA,答案就是套路的d[x]+d[y]-d[lca]*2 然后就可以发现,其 ...

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

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

随机推荐

  1. 用虚拟机安装Linux系统的过程

    1.打开VMware->点击File->点击New Virtual Machine.. 2.我们选择Custom并点击Next 3.保持默认然后点next 4.选择图中所示内容,点Next ...

  2. yii 常用一些调用 (增加中)

    调用YII框架中 jquery:Yii::app()->clientScript->registerCoreScript('jquery');        framework/web/j ...

  3. 深入浅出数据结构C语言版(1)——什么是数据结构及算法

    在很多数据结构相关的书籍,尤其是中文书籍中,常常把数据结构与算法"混合"起来讲,导致很多人初学时对于"数据结构"这个词的意思把握不准,从而降低了学习兴趣和学习信 ...

  4. spring(一) IOC讲解

    spring基本就两个核心内容,IOC和AOP.把这两个学会了基本上就会用了. --WH 一.什么是IOC? IOC:控制反转,通俗点讲,将对象的创建权交给spring,我们需要new对象,则由spr ...

  5. J2那几个E和Web基础

    收到PHP童鞋的反馈: 我觉得不用讲太基础的语法,基础语法大家自己去看,主要讲讲java web开发的一个流程,从开始写代码,到编译,发布,上线,回滚整个流程 大体上的环节,以及需要用到哪些工具 具体 ...

  6. Asp.net SignalR 应用并实现群聊功能 开源代码

    ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务 ...

  7. npm 配置和安装 express4.X 遇到的问题及解决

    前言:懒得看前面两篇介绍的也可以从本节直接参考,但建议最好了解下,因为 4.X 的express 已经把命令行工具分离出来 (链接https://github.com/expressjs/genera ...

  8. SpringBoot-SpringMvc的Interceptor拦截器配置

    Interceptor拦截器实现对每一个用户请求处理前后的业务处理,比如我们需要对用户请求进行响应时间的记录,需要记录请求从开始到结束所耗的时间,这时我们就需要用到拦截器了 下面我们以记录请求处理时间 ...

  9. onclick = xxx这种赋值写法绑定事件的原理是什么?

    本文转自知乎貘吃馍香的回答 提问:刚入门不久,能力有限,这个问题我描述起来有点困难,只有劳烦各位大神细看了 我之前一直以为js底层存在类似下面这样的代码: //给所有dom对象定义好onclick值为 ...

  10. js原型对象

    原型对象是什么? 在js中,每一个创建的的函数都会有一个prototype属性,这个属性指向一个对象,这个对象就是原型对象 function lla(){} console.log(lla.proto ...