与基环树最短路的思想相同
我们只需要对每个子树求lca,在环上我们以d数组记录一个同向的前缀路径长度
可以方便的算出环上两点之间的最短距离,也就是环两侧距离取min,具体看注释
当我们求x与y之间的距离时
可以分类讨论:
1.如果x和y的lca是y或x

2.如果x和y的lca没在环里

3.如果x和y的lca在环里

算法实现
设1为根
第一步:spfa求到根的最短路dis
第二步:dfs找环,重新建图,断开环上的边,将环上的点连向环的最高点
第三步:bfs计算子树的深度dep和lca用的f数组
第四步:求lca顺便求出两点距离
具体实现还看代码及注释:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define maxn 10010
#define maxm 80010
using namespace std;
int n,m,dep[maxn],fa[maxn],q,now;
int cnt=1,head[maxn],dis[maxn],len[maxn],tot;
int dfn[maxn],num,f[maxn][16],d[maxn],g[maxn];
bool vis[maxn],del[maxm];//我不会告诉你我f数组第二维开成了1<<15 tle了七八回struct EDGE{int to,nxt,frm,w;
}edge[maxm];void add(int x,int y,int z){cnt++;edge[cnt].to=y;edge[cnt].nxt=head[x];edge[cnt].w=z;head[x]=cnt;
}
// 建图,断边,将环上的点与最高点连一条0权边
void circle(int x,int e){int y=x,i; x=edge[e].to;len[++tot]=edge[e].w; g[y]=tot;del[e]=del[e^1]=1; add(x,y,0); add(y,x,0);//del为断边操作for(i=fa[y];(y=edge[i^1].to)!=x;i=fa[y]){len[tot]+=edge[i].w; g[y]=tot;del[i]=del[i^1]=1; add(x,y,0); add(y,x,0);}len[tot]+=edge[i].w;
}
//dfs用dfs序找环
void dfs(int x){dfn[x]=++num;for(int i=head[x];i;i=edge[i].nxt){if(i>now) continue;//这里如果是后加进来的边说明是环上被处理过的,不管他int v=edge[i].to;if(!dfn[v]){fa[v]=i;//fa存的是通往这个点的边d[v]=d[x]+edge[i].w;//d数组是环上的点到环的最高点的距离dfs(v);}else if(fa[x]!=(i^1) && dfn[v]<dfn[x]) circle(x,i);}//如果u的dfs序比v大说明找到了环
}
//单源最短路
void spfa(int s){queue<int> qq;memset(dis,0x3f,sizeof dis);qq.push(s); vis[s]=1; dis[s]=0;while(!qq.empty()){int u=qq.front(); qq.pop();vis[u]=0;for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].to;if(dis[v]>dis[u]+edge[i].w){dis[v]=dis[u]+edge[i].w;if(!vis[v]) qq.push(v),vis[v]=1;}}}
}
//bfs求深度和lca的f数组预处理
void bfs(){queue<int> qq; while(!qq.empty()) qq.pop();memset(vis,0,sizeof vis);qq.push(1); vis[1]=1; dep[1]=1;while(!qq.empty()){int u=qq.front(); qq.pop();for(int i=head[u];i;i=edge[i].nxt){if(del[i]) continue;//如果这条边断开了就不再搜,相当于只处理子树的lcaint v=edge[i].to;if(!vis[v]){dep[v]=dep[u]+1; f[v][0]=u;for(int j=1;j<15;j++) f[v][j]=f[f[v][j-1]][j-1];qq.push(v); vis[v]=1;}}}
}
//求lca
int lca(int x,int y){if(dep[x]<dep[y]) swap(x,y);int p=x,q=y;for(int i=14;i>=0;i--)if(dep[f[x][i]]>=dep[y]) x=f[x][i];//常规操作if(x==y) return dis[p]-dis[q];//在一条链上for(int i=14;i>=0;i--)if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];if(g[x]&&g[x]==g[y]) //lca在环上,则环两侧取min{int ww=abs(d[x]-d[y]);return dis[p]-dis[x]+dis[q]-dis[y]+min(ww,len[g[x]]-ww);}return dis[p]+dis[q]-2*dis[f[x][0]];//不在环上也不在同一条链上
}int main(){scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=m;i++){int x, y, z; scanf("%d%d%d",&x,&y,&z);add(x,y,z); add(y,x,z);}spfa(1);//第一步以1为根求最短路now=cnt;//这里是记录一下初始时边的编号到哪儿dfs(1);//以1出发找环bfs();//bfs求深度和f数组for(int i=1;i<=q;i++){int x,y; scanf("%d%d",&x,&y);printf("%d\n",lca(x,y));//lca}return 0;
}

仙人掌最短路--bzoj2125相关推荐

  1. BZOJ 2125 最短路 仙人掌最短路

    为了证明我还活着所以我发了篇博客_ (:з」∠) _ 题意: 给定一张仙人掌图,n<=10000,多次询问两点间最短路. Q<=10000. 解析: 首先如果这是一棵树的话,那么我们只需要 ...

  2. 洛谷 :P5236 【模板】静态仙人掌(圆方树模板 + 仙人掌最短路)

    题意很简单,在仙人掌图上求两点的最短路. 做法:需要用到圆方树 先来看看什么是圆方树:圆方树,就是由仙人掌图转化而来,树上分两种点:圆点和方点,圆点是仙人掌图上的点,方点是由仙人掌的环转化而来. 由于 ...

  3. 仙人掌问题(圆方树)

    [算法简介] 仙人掌就是把树上多连了一些返祖边,构成了一些环 根据仙人掌这个名字我们也可以较为形象的感受到图的形态 具体的,仙人掌分为点仙人掌和边仙人掌,定义分别为点/边最多属于一个环 之所以把这样的 ...

  4. 2125: 最短路/3047: Freda的传呼机

    题目链接 题目大意:静态仙人掌最短路 题解:丢链接跑-- 我的收获:233333 //From popoqqq #include <map> #include <vector> ...

  5. 孤立森林算法 python_孤立森林(isolation forest)

    1.简介 孤立森林(Isolation Forest)是另外一种高效的异常检测算法,它和随机森林类似,但每次选择划分属性和划分点(值)时都是随机的,而不是根据信息增益或者基尼指数来选择. 在建树过程中 ...

  6. 存档……【假装自己会刷题【怎么写着写着成了日记啊

    2017.4.9 AFO 2017.2.27 嗨呀--昨天补了半天觉--十二点十分起床,稳,只有十二个小时的周末.rmvb 然后--下午来学校开黑,由于车速太快,一万个人翻车被skipped[捂脸]- ...

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

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

  8. BZOJ2125 最短路

    每个点有两个值,一个是从根到这个点的最短路d[i],一个是从根沿dfs树到这个点的距离rd[i]. 之后是一个很牛逼的建图,把环上的点都连到环中深度最浅的点得到一颗树,并维护每个点所在的环以及每个环的 ...

  9. [BZOJ2125]最短路

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

最新文章

  1. redis trie
  2. jwPlayer实现支持IE8及以下版本避免出错的方法
  3. 【博客管理】博客新建栏目的添加—HTML格式书写规范
  4. Netflix:如何打造开放协作的实时 ETL 平台?
  5. JAVA异常处理实战心得
  6. Honeywell 1900 条码阅读器
  7. 无人机辅助移动边缘计算的计算卸载优化:一种深度确定性策略梯度方法(6)——代码实现
  8. win10喇叭没声音,Realtek高清音频管理器 打不开问题解决
  9. 计算机网络谢希仁课后答案详解+计算机网络释疑与习题解答PDF+各章重点题目
  10. 【牛客网】马三来刷题之串的模式匹配
  11. 如何利用github打造博客专属域名
  12. ORA-24761: transaction rolled back
  13. 网上选课系统算法了解
  14. 如何开展业务是我在离开X网之后重新学的
  15. 成为研究生后你都明白了什么?
  16. c语言父子线程交替打印,多线程面试题之【三线程按顺序交替打印ABC的方法】...
  17. TI DSP 6657 SRIO 简介
  18. python中关系运算符惰性求值_python对象属性惰性取值
  19. 这个行情,币圈小白该如何生存?
  20. java程序员的转正述职ppt

热门文章

  1. IDE(20)——常用的 Java IDE
  2. 2013数学建模B题碎纸片拼接复原参考资料
  3. linux+n天没有访问文件夹,linux文件目录与管理
  4. 椭圆切线方程公式的推导过程
  5. swal 弹框确定ajax,前端常用效果(layer/swal)
  6. gif加文字 php,教你给GIF动态图片加文字
  7. 红黑树封装实现树形结构的关联式容器(map,set)
  8. 如何免费获取百度文档,简单实用,2013亲测
  9. Asp.NET Core简介
  10. python数据分析-matplotlib总结