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.直 ...
随机推荐
- 观察者模式在Foundation框架通知中的应用
GitHub传送门 1.何为观察者模式? 观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新. 举个简单的例子:你和你的舍友都订阅了 ...
- 08Microsoft SQL Server 数据查询
Microsoft SQL Server 数据查询 单表查询所有列 --查询所有行所有列 select all * from table; --查询不重复行的所有列 select distinct * ...
- C++ Primer(第4版)-学习笔记-第5部分:高级主题
第17章 用于大型程序的工具 异常处理 不存在数组或函数类型的异常.相反,如果抛出一个数组,被抛出的对象转换为指向数组首元素的指针,类似地,如果抛出一个函数,函数被转换为指向该函数的指针. 不要抛出 ...
- [BOI2008]Elect 选举
背包. #include <algorithm> #include <iostream> #include <cstdlib> #include <cstri ...
- Python使用Flask框架,结合Highchart,搭配数据功能模块处理csv数据
参考链接:https://www.highcharts.com.cn/docs/data-modules 1.javascript代码 var csv = document.getElementByI ...
- 【Codeforces 279C】Ladder
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 设pre[i]表示i往前一直递增能递增多远 设aft[i]表示i往后一直递增能递增多远 如果aft[l]+pre[r]>=(r-l+1) ...
- 【Codeforces 988D】Points and Powers of Two
[链接] 我是链接,点我呀:) [题意] 让你从一个集合中找出来一个子集 使得这个子集中任意两个数相减的绝对值是2^的整数次幂 且集合的大小最大 [题解] 考虑子集的个数为4个或4个以上 那么我们找到 ...
- Codeforces 263A. Appleman and Easy Task
A. Appleman and Easy Task time limit per test 1 second memory limit per test 256 megabytes input ...
- [luoguP3690] 【模板】Link Cut Tree
传送门 处理路径 xor 和的时候可以维护子树 xor 和,先提取出路径,再把一个点 splay 到最上方,直接取子树 xor 和即可. 更新一个点权时可以先提取出根到这个点的路径,把这个点 spla ...
- Drools介绍与使用
Drools 是用 Java 语言编写的开放源码规则引擎,使用 Rete 算法对所编写的规则求值.Drools 允许使用声明方式表达业务逻辑.可以使用非 XML 的本地语言编写规则,从而便于学习和理解 ...