题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2125

仙人掌!模仿 lyd 的代码写的,也算是努力理解了;

主要分成 lca 在环上和不在环上,先缩环(环上的点直接连向最高点),那么不在环上的 lca 就跟在树上一样求法;

在环上的话就先求出环外部分,再计算环内距离;

所以一遍 spfa 求从根出发的最短路,再一遍 dfs 求 dfs 序的 dis ,用来处理环上距离,然后 bfs 计算深度用来倍增求 lca,然后分类求答案即可;

注意边数就是点的4倍,还要算上缩环时连的边。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
int const maxn=,maxm=;//
int n,m,Q,hd[maxn],ct=,dis[maxn],dist[maxn],cr,col[maxn],tim,dfn[maxn];
int fa[maxn],len[maxn],f[maxn][],dep[maxn];
bool del[maxm],vis[maxn];
queue<int>q;
struct N{
int to,nxt,w;
N(int t=,int n=,int w=):to(t),nxt(n),w(w) {}
}ed[maxm];
void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
int ab(int x){return x<?-x:x;}
void spfa()
{
memset(dist,0x3f,sizeof dist);
memset(vis,,sizeof vis);
dist[]=; q.push(); vis[]=;
while(q.size())
{
int x=q.front(); q.pop(); vis[x]=;
for(int i=hd[x],u;i;i=ed[i].nxt)
if(dist[u=ed[i].to]>dist[x]+ed[i].w)
{
dist[u]=dist[x]+ed[i].w;
if(!vis[u])vis[u]=,q.push(u);
}
}
}
void make(int x,int e)
{
int i,y=x; x=ed[e].to;
len[++cr]+=ed[e].w; col[y]=cr; del[e]=del[e^]=;
add(x,y,); add(y,x,);//!连向最高点
for(i=fa[y];(y=ed[i^].to)!=x;i=fa[y])
{
len[cr]+=ed[i].w; col[y]=cr;
del[i]=del[i^]=;
add(x,y,); add(y,x,);//!连向最高点
}
col[x]=cr; len[cr]+=ed[i].w;
}
void dfs(int x)
{
dfn[x]=++tim;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if(!dfn[u=ed[i].to])
{
fa[u]=i; dis[u]=dis[x]+ed[i].w;
dfs(u);
}
else if(dfn[u]<dfn[x]&&fa[x]!=(i^))make(x,i);
}
}
void bfs()
{
while(q.size())q.pop();
memset(vis,,sizeof vis);
vis[]=; q.push(); dep[]=;
while(q.size())
{
int x=q.front(); q.pop();
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if(vis[u=ed[i].to]||del[i])continue;
vis[u]=; dep[u]=dep[x]+; f[u][]=x;
for(int j=;j<=;j++)f[u][j]=f[f[u][j-]][j-];
q.push(u);
}
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int a=x,b=y;
int k=dep[x]-dep[y];
for(int i=;i<=;i++)
if(k&(<<i))x=f[x][i];
if(x==y)return dist[a]-dist[b];
for(int i=;i>=;i--)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
if(col[x]&&col[x]==col[y])
{
int l=ab(dis[x]-dis[y]);
return dist[a]-dist[x]+dist[b]-dist[y]+min(l,len[col[x]]-l);
//两个点从环外跳到环上,所以先加上环外部分的 dist,再算环上的最短距离
}
return dist[a]+dist[b]-*dist[f[x][]];
}
int main()
{
scanf("%d%d%d",&n,&m,&Q);
for(int i=,x,y,z;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
spfa();
dfs();
bfs();
for(int i=,x,y;i<=Q;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
}

bzoj2125 最短路——仙人掌两点间距离的更多相关文章

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

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

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

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

  3. bzoj2125 最短路

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

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

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

  5. BZOJ.2125.最短路(仙人掌 最短路Dijkstra)

    题目链接 多次询问求仙人掌上两点间的最短路径. 如果是在树上,那么求LCA就可以了. 先做着,看看能不能把它弄成树. 把仙人掌看作一个图(实际上就是),求一遍根节点到每个点的最短路dis[i]. 对于 ...

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

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

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

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

  8. 【题解】Bzoj2125最短路

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

  9. bzoj 2125 最短路——仙人掌两点间最短路

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2125 因为看了TJ又抄了标程,现在感觉还是轻飘飘的……必须再做一遍. 两点间的情况: 1.直 ...

随机推荐

  1. RabbitMQ系列(三)--Java API

    基于java使用RabbitMQ 框架:SpringBoot1.5.14.RELEASE maven依赖: <dependency> <groupId>com.rabbitmq ...

  2. JS函数assign

    Object函数提供了一个叫做assign的函数,用来合并多个对象. Object.assign(...): 你可以传递多个对象给该函数,这些对象中的自有且可枚举的属性,会被拷贝给第一个对象. var ...

  3. ProgressDialog的样式

    ProgressDialog的样式有两种,一种是圆形不明确状态,一种是水平进度条状态 第一种方式:圆形进度条 final ProgressDialog dialog = new ProgressDia ...

  4. swift中tableview的使用和注意事项

    今天使用swift写了个简单的tableView,语法和用法上跟oc没多大的区别.但是还是有一些细节的地方需要注意一下的. 先上代码 import UIKit class ViewController ...

  5. The content of element type "resultMap" must match ...

    mybatis中的mapper文件错误 ①错误原因: <resultMap>标签中需要按照一下顺序编写: <id> <result> <association ...

  6. BZOJ 2806 Luogu P4022 [CTSC2012]Cheat (广义后缀自动机、DP、二分、单调队列)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2806 (luogu) https://www.luogu.org/pro ...

  7. 【Codeforces 493D】Vasya and Chess

    [链接] 我是链接,点我呀:) [题意] [题解] 会发现两个皇后之间如果只有奇数个位置 也就是n%2==1 那么第二个人总是赢的 因为如果white往下跑的话,black也能往下跑. 第二个人没有输 ...

  8. ceph 简介

    Ceph 存储集群 数据的存储 伸缩性和高可用性 CRUSH 简介 集群运行图 高可用监视器 高可用性认证 智能程序支撑超大规模 动态集群管理 关于存储池 PG 映射到 OSD 计算 PG ID 互联 ...

  9. POJ 2142 TheBalance 模线性方程求解

    题目大意: 就是将两种砝码左右摆放,能够在物品放置在天平上时保持平衡 很容易得到 ax + by = t的模线性方程 按题目要求,希望首先满足 |x| + |y| 最小 , 如果有多种情况,再满足所有 ...

  10. vim下多行注释与解注释

    1.多行注释 (1)按esc进入命令行模式 (2)按下Ctrl+v,进入区块模式,并使用上下键选择需要注释的多行 (3)按下“I”(大写)键,进入插入模式 (4)输入注释符(“//”或“#”等) (5 ...