bzoj2125 最短路——仙人掌两点间距离
题目: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 最短路——仙人掌两点间距离的更多相关文章
- BZOJ2125 最短路 【仙人掌最短路】
题目 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. 输入格式 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一 ...
- [BZOJ2125]最短路(圆方树DP)
题意:仙人掌图最短路. 算法:圆方树DP,$O(n\log n+Q\log n)$ 首先建出仙人掌圆方树(与点双圆方树的区别在于直接连割边,也就是存在圆圆边),然后考虑点u-v的最短路径,显然就是:在 ...
- bzoj2125 最短路
Description 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. Input 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个 ...
- BZOJ2125 最短路 圆方树、倍增
传送门 对仙人掌建立圆方树,然后对边定权 对于圆点和圆点之间的边,是原来仙人掌上的桥,边权保持不变 对于圆点和方点之间的边,将圆方树看做以一个圆点为根的有根树之后,一个方点的父亲一定是一个圆点.对于这 ...
- BZOJ.2125.最短路(仙人掌 最短路Dijkstra)
题目链接 多次询问求仙人掌上两点间的最短路径. 如果是在树上,那么求LCA就可以了. 先做着,看看能不能把它弄成树. 把仙人掌看作一个图(实际上就是),求一遍根节点到每个点的最短路dis[i]. 对于 ...
- 2018.07.25 bzoj2125: 最短路(圆方树+倍增)
传送门 人生的第一道仙人掌. 这道题求是仙人掌上的最短路. 先建出圆方树,然后用倍增跑最短路,当lca" role="presentation" style=" ...
- [BZOJ2125]最短路[圆方树]
题意 给定仙人掌,多次询问两点之间的最短路径. \(n\le 10000, Q\le 10000\) 分析 建出圆方树,分路径 lca 是圆点还是方点讨论. 预处理出根圆点到每个圆点的最短距离 \( ...
- 【题解】Bzoj2125最短路
处理仙人掌 ---> 首先建立出圆方树.则如果询问的两点 \(lca\) 为圆点,直接计算即可, 若 \(lca\) 为方点,则需要额外判断是走环的哪一侧(此时与两个点在环上的相对位置有关.) ...
- bzoj 2125 最短路——仙人掌两点间最短路
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2125 因为看了TJ又抄了标程,现在感觉还是轻飘飘的……必须再做一遍. 两点间的情况: 1.直 ...
随机推荐
- ThinkPHP---案例--实现知识管理功能
[一]准备工作 (1)数据表sp_knowledge SQL语句:知识管理数据表结构 create table sp_knowledge( id int(11) not null auto_incre ...
- 16 this和super和构造代码块
this关键词---当前类的对象的引用 public class Public { String name; int age; public static void main(String[] arg ...
- Python学会之后,一般能拿到多少工资?
Python在约40年前出现以来,已经有数以千计基于这项技术的网站和软件项目,Python因其独有的特点从众多开发语言中脱颖而出,深受世界各地的开发者喜爱. 随着Python的技术的流行,Python ...
- jquery 五星评价(图片实现)
1111 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...
- 数字图像处理技术在TWaver可视化中的应用
数字图像处理(Digital Image Processing)又称为计算机图像处理,它是指将图像信号转换成数字信号并利用计算机对其进行处理的过程.常用的图像处理方法有图像增强.复原.编码.压缩等,数 ...
- HDU - 6266 - HDU 6266 Hakase and Nano (博弈论)
题意: 有两个人从N个石子堆中拿石子,其中一个人可以拿两次,第二个人只能拿一次.最后拿完的人胜利. 思路: 类型 Hakase先 Hakase后 1 W L 1 1 W W 1 1 1 (3n) L ...
- python_ 学习笔记(运算符)
python的运算符基本和C语言一致,以下说一些不一样的! 算术运算符 **:代表乘方,对应也有**=: //:代表商向下取整,对应也有//=: 逻辑运算符 and or not 位运算符 :& ...
- pandas处理各类表格数据
经常遇到Python读取excel和csv还有其他各种文件的内容.json还有web端的读取还是比较简单,但是excel和csv的读写是很麻烦.这里记录了pandas库提供的方法来实现文本内容和Dat ...
- 洛谷 1937 [USACO10MAR]仓配置Barn Allocation
[题解] 贪心. 把区间按照右端点从小到大排序,右端点相同的按照长度从小到大排序,然后按顺序考虑,能放就放下去. 维护能不能放下去用线段树即可. #include<cstdio> #inc ...
- MessageFormat理解,MessageFormat.format(Object obj)方法
MessageFormat.format(Object obj)方法主要用途为拼接message信息 用法: Object[] testArgs = {new String("张三" ...