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

因为看了TJ又抄了标程,现在感觉还是轻飘飘的……必须再做一遍。

两点间的情况:

1.直到 lca 都没有在一个环上的部分;

2.本来就处在一个环上;

3.本来不在一个环上,快到 lca 的时候开始处在一个环上了。

第一种情况就普通弄就行。处理倍增 lca 数组和根到每个点的最短路dis值。

第二种情况在环上两部分取较短的就行。

第三种情况是前两种的结合。需要找到 p 和 q 刚开始在同一个环上时的那两个进入点 x 和 y。然后dis[ p ] - dis[ x ] + dis[ q ] - dis[ y ]再加上 p、q 环上两部分较短的。

怎么取较短的呢?

可以弄dfs序的距离。

实现的时候第二种和第三种情况可以合并。

细节有一些不明白:环的最高点的深度和环上别的点不一样,也行吗?还有边的数组大小怎么算?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=1e4+;
int n,m,q,hd[N],xnt=,g[N],len[N],cnt,dep[N],f[N][];
int dis[N],ds[N],fa[N],dfn[N],tim;
bool vis[N];
struct Ed{
int nxt,to,w;bool del;
Ed(int n=,int t=,int w=):nxt(n),to(t),w(w) {del=;}
}ed[N<<];
int tabs(int k){return k<?-k:k;}
void add(int x,int y,int z)
{
ed[++xnt]=Ed(hd[x],y,z);hd[x]=xnt;
}
void spfa()
{
memset(dis,0x3f,sizeof dis);dis[]=;
queue<int> q;q.push();vis[]=;
while(q.size())
{
int k=q.front();q.pop();vis[k]=;//don't forget visk=0!!
for(int i=hd[k],v;i;i=ed[i].nxt)
if(dis[v=ed[i].to]>dis[k]+ed[i].w)
{
dis[v]=dis[k]+ed[i].w;
if(!vis[v])vis[v]=,q.push(v);
}
}
}
void circle(int y,int e)
{
int x=ed[e].to;//!
len[++cnt]=ed[e].w;g[y]=cnt;
ed[e].del=ed[e^].del=;//don't forget del!
add(x,y,);add(y,x,);// edw has no limit--only for bfs the dep
// edw is guaranteed by ds[]
for(e=fa[y];(y=ed[e^].to)!=x;e=fa[y])
{
len[cnt]+=ed[e].w;g[y]=cnt;ed[e].del=ed[e^].del=;
add(x,y,);add(y,x,);
}
len[cnt]+=ed[e].w;g[x]=cnt;
}
void dfs(int cr)
{
dfn[cr]=++tim;
for(int i=hd[cr],v;i;i=ed[i].nxt)
if(!dfn[v=ed[i].to])
{
fa[v]=i;ds[v]=ds[cr]+ed[i].w;dfs(v);
}
else if(i!=(fa[cr]^)&&dfn[v]<dfn[cr])circle(cr,i);//cr!!!
}
void bfs()
{
queue<int> q;q.push();dep[]=;
while(q.size())
{
int k=q.front();q.pop();
for(int i=hd[k],v;i;i=ed[i].nxt)
if(!ed[i].del&&!dep[v=ed[i].to])
{
dep[v]=dep[k]+;q.push(v);
f[v][]=k;
for(int j=;j<=;j++)//j not i
{
f[v][j]=f[f[v][j-]][j-];
}
}
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int p=x,q=y;
for(int i=;i>=;i--)
if(dep[f[x][i]]>=dep[y])x=f[x][i];
if(x==y)return dis[p]-dis[q];
for(int i=;i>=;i--)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
if(g[x]!=g[y]||(!g[x]&&!g[y]))return dis[p]+dis[q]-*dis[f[x][]];//&& !g[x]&&!g[y]!!!
int k=tabs(ds[x]-ds[y]);
return dis[p]-dis[x]+dis[q]-dis[y]+min(k,len[g[x]]-k);
// include p&q in different circle but x&y in the same circle;
//because the dep of nodes in the same circle are almost the same
}
int main()
{
scanf("%d%d%d",&n,&m,&q);int x,y,z;
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
spfa();
dfs();
bfs();
for(int i=;i<=q;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
return ;
}

bzoj 2125 最短路——仙人掌两点间最短路的更多相关文章

  1. hdu 2544 最短路(两点间最短路径)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2544 方法一:dijkstra算法,求两点之间最短路径. /*********************** ...

  2. bzoj 1023: [SHOI2008]cactus仙人掌图 2125: 最短路 4728: 挪威的森林 静态仙人掌上路径长度的维护系列

    %%% http://immortalco.blog.uoj.ac/blog/1955 一个通用的写法是建树,对每个环建一个新点,去掉环上的边,原先环上每个点到新点连边,边权为点到环根的最短/长路长度 ...

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

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

  4. boost dijkstra获得两点间的最短路

    需求是只需要得到两点间的最短路,不需要求得单源对于全图的最短路,使用boost中的dijsktra_shortest_path,当得到目标点的最短路时直接throw exception. #inclu ...

  5. 【刷题】BZOJ 2125 最短路

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

  6. [C++]boost dijkstra获得两点间的最短路

    需求是只需要得到两点间的最短路,不需要求得单源对于全图的最短路,使用boost中的dijsktra_shortest_path,当得到目标点的最短路时直接throw exception. #inclu ...

  7. [CF1051F]The Shortest Statement (LCA+最短路)(给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路)

    题目:给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路 n≤100000,m≤100000,m-n≤20. 首先看到m-n≤20这条限制,我们可以想到是围绕这个20来做这道题. 即如果我们 ...

  8. AOJ GRL_1_C: All Pairs Shortest Path (Floyd-Warshall算法求任意两点间的最短路径)(Bellman-Ford算法判断负圈)

    题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C All Pairs Shortest Path Input ...

  9. 用 Excel 测试“绘制两点间连线”的算法

    最近在研究和制作数字示波器,其中涉及一个小算法:需要将 ADC 采样的数值在 TFT LCD 屏幕上面显示并且用“线”连接起来. ADC 按照时序对输入电压采样后,记录的是一个个的数值,如果显示的时候 ...

随机推荐

  1. Inside a super fast CSS engine: Quantum CSS (aka Stylo)

    https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/?utm_source=d ...

  2. BZOJ3211花神游历各国

    BZOJ3211花神游历各国 BZOJ luogu 分块 记一个all表示该块是否全部<=1,如果all不为真就暴力修改 因为一个数被开根的次数不多,即使\(10^{12}\)只要开根6次也会变 ...

  3. (转)Javascript模块化编程(一):模块的写法

    随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂. 网页越来越像桌面程序,需要一个团队分工协作.进度管理.单元测试等等......开发者 ...

  4. Intel IPP 图像空间转换

    一. 背景 用QuickSync VPP模块做RGBA到NV12的颜色空间转换导致文字显示蒙上一层颜色的问题, 暂时怀疑是VPP自身的问题,因为参数设置都是按官方demo设置的.所以尝试使用IPP来做 ...

  5. python中的一些坑(待补充)

    函数默认参数使用可变对象 def use_mutable_default_param(idx=0, ids=[]): ids.append(idx) print(idx) print(ids) use ...

  6. LeetCode:删除排序数组中的重复项||【80】

    LeetCode:删除排序数组中的重复项||[80] 题目描述 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原 ...

  7. persisted? vs new_record?

    https://joe11051105.gitbooks.io/you-need-to-know-about-ruby-on-rails/content/activerecord/persisted_ ...

  8. [原创]java WEB学习笔记19:初识MVC 设计模式:查询,删除 练习(理解思想),小结 ,问题

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  9. Android进程间通信(IPC)机制Binder简要介绍和学习计划【转】

    本文转载自:http://blog.csdn.net/luoshengyang/article/details/6618363 在Android系统中,每一个应用程序都是由一些Activity和Ser ...

  10. POJ Layout

    A - Layout Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit S ...