题目

给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。

输入格式

输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一条无向边v-u,长度为w 最后Q行,每行两个整数v,u表示一组询问

输出格式

输出Q行,每行一个整数表示询问的答案

输入样例

9 10 2

1 2 1

1 4 1

3 4 1

2 3 1

3 7 1

7 8 2

7 9 2

1 5 3

1 6 4

5 6 1

1 9

5 7

输出样例

5

6

提示

对于100%的数据,N<=10000,Q<=10000

题解

仙人掌的题目,都与树上的方法相联系,再考虑环的影响

首先如果在树上,我们设d[u]表示u到根的距离,两点u,v的距离dis=d[u]+d[v]−2∗d[lca]

现在加上几个环,我们先跑一遍dfs找出所有的环以及算出d[],然后重构树,将环上的点全部连到该环最高点上,距离为环上到最高点的最短路

这样子构建出来的树,我们可以用倍增套用树的方法求解

如果求解时两点倍增时算得的最后祖先属于同一个环,那么就考虑环的贡献

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. #define LL long long int
  7. #define REP(i,n) for (int i = 1; i <= (n); i++)
  8. #define Redge(u) for (int k = h[u]; k; k = ed[k].nxt)
  9. using namespace std;
  10. const int maxn = 10005,maxm = 100005,INF = 1000000000;
  11. inline int RD(){
  12. int out = 0,flag = 1; char c = getchar();
  13. while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
  14. while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
  15. return out * flag;
  16. }
  17. int N,M,Q,h[maxn],ne = 2;
  18. struct EDGE{int to,nxt,w;}ed[maxm];
  19. inline void build(int u,int v,int w){
  20. ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
  21. ed[ne] = (EDGE){u,h[v],w}; h[v] = ne++;
  22. }
  23. int h2[maxn];
  24. struct E{int to,nxt;}e[2 * maxn];
  25. inline void add(int u,int v){e[ne] = (E){v,h2[u]}; h2[u] = ne++;}
  26. int dfn[maxn],low[maxn],d[maxn],dep[maxn],cnt = 0;
  27. int fa[maxn][20],dis[maxn][20];
  28. int cir[maxn],siz[maxn];
  29. void getcir(int rt,int k){
  30. int to = ed[k].to,len = d[to] - d[rt] + ed[k].w;
  31. siz[++siz[0]] = len;
  32. for (int i = to; i != rt; i = fa[i][0]){
  33. add(rt,i);
  34. dis[i][0] = min(d[i] - d[rt],len - d[i] + d[rt]);
  35. cir[i] = siz[0];
  36. }
  37. }
  38. void dfs(int u){
  39. dfn[u] = low[u] = ++cnt; int to;
  40. Redge(u) if ((to = ed[k].to) != fa[u][0]){
  41. if (!dfn[to]){
  42. fa[to][0] = u;
  43. d[to] = d[u] + ed[k].w;
  44. dfs(to);
  45. low[u] = min(low[u],low[to]);
  46. }else low[u] = min(low[u],dfn[to]);
  47. if (dfn[u] < low[to]) add(u,to),dis[to][0] = ed[k].w;
  48. }
  49. Redge(u) if (fa[to = ed[k].to][0] != u && dfn[u] < dfn[to])
  50. getcir(u,k);
  51. }
  52. void dfs2(int u){
  53. REP(i,15){
  54. fa[u][i] = fa[fa[u][i - 1]][i - 1];
  55. dis[u][i] = dis[u][i - 1] + dis[fa[u][i - 1]][i - 1];
  56. }
  57. for (int k = h2[u],to; k; k = e[k].nxt){
  58. fa[to = e[k].to][0] = u; dep[to] = dep[u] + 1;
  59. dfs2(to);
  60. }
  61. }
  62. int solve(int u,int v){
  63. if (dep[u] < dep[v]) swap(u,v);
  64. int ans = 0,D = dep[u] - dep[v];
  65. for (int i = 0; (1 << i) <= D; i++)
  66. if ((1 << i) & D) ans += dis[u][i],u = fa[u][i];
  67. if (u == v) return ans;
  68. for (int i = 15; i >= 0; i--)
  69. if (fa[u][i] != fa[v][i]){
  70. ans += dis[u][i] + dis[v][i];
  71. u = fa[u][i]; v = fa[v][i];
  72. }
  73. if (cir[u] && cir[u] == cir[v])
  74. ans += min(abs(d[u] - d[v]),siz[cir[u]] - abs(d[u] - d[v]));
  75. else ans += dis[u][0] + dis[v][0];
  76. return ans;
  77. }
  78. int main(){
  79. N = RD(); M = RD(); Q = RD(); int a,b,w;
  80. while (M--) a = RD(),b = RD(),w = RD(),build(a,b,w);
  81. ne = 1;
  82. dfs(1);
  83. dep[1] = 1;
  84. dfs2(1);
  85. while (Q--){
  86. a = RD(); b = RD();
  87. printf("%d\n",solve(a,b));
  88. }
  89. return 0;
  90. }

BZOJ2125 最短路 【仙人掌最短路】的更多相关文章

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

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

  2. poj 3463 Sightseeing( 最短路与次短路)

    http://poj.org/problem?id=3463 Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissio ...

  3. 最短路和次短路问题,dijkstra算法

    /*  *题目大意:  *在一个有向图中,求从s到t两个点之间的最短路和比最短路长1的次短路的条数之和;  *  *算法思想:  *用A*求第K短路,目测会超时,直接在dijkstra算法上求次短路; ...

  4. UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

    最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同 ...

  5. POJ---3463 Sightseeing 记录最短路和次短路的条数

    Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9247   Accepted: 3242 Descr ...

  6. hdu1688(dijkstra求最短路和次短路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1688 题意:第k短路,这里要求的是第1短路(即最短路),第2短路(即次短路),以及路径条数,最后如果最 ...

  7. CF 672C 两个人捡瓶子 最短路与次短路思想

    C. Recycling Bottles time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  8. POJ 3463 Sightseeing 【最短路与次短路】

    题目 Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the ...

  9. POJ - 3463 Sightseeing 最短路计数+次短路计数

    F - Sightseeing 传送门: POJ - 3463 分析 一句话题意:给你一个有向图,可能有重边,让你求从s到t最短路的条数,如果次短路的长度比最短路的长度多1,那么在加上次短路的条数. ...

随机推荐

  1. [转] vim配置python自动补全

    vim python自动补全插件:pydiction 可以实现下面python代码的自动补全: 1.简单python关键词补全 2.python 函数补全带括号 3.python 模块补全 4.pyt ...

  2. 虚拟机linux桥接联网问题

    Linux系统为redhat5.8 虚拟机的版本:vm8.0 本人刚刚开始接触linux,今日需要通过linux进行联网,因此也学习了一点点关于虚拟机的联网的知识,在此与大家进行分享,希望大家可以之处 ...

  3. 浅谈UWB(超宽带)室内定位技术(转载)

    技术背景 随着无线通信技术的发展和数据处理能力的提高,基于位置的服务成为最有前途的互联网业务之一.无论移动在室内还是室外环境下,快速准确地获得移动终端的位置信息和提供位置服务的需求变得日益迫切.通信和 ...

  4. python——matplotlib图像的基本处理

    1.绘制图像中的点和线 from PIL import Image from pylab import * im = array(Image.open('E:\Python\meinv.jpg')) ...

  5. Mybatis中updateByPrimaryKeySelective和updateByPrimaryKey区别

    int updateByPrimaryKeySelective(TbItem record); int updateByPrimaryKey(TbItem record); 上面的是逆转工程生成的Ma ...

  6. Git-历史穿梭

    图形工具:gitk gitk是最早实现的一个图形化的Git版本库浏览器软件,基于tcl/tk实现,因此gitk非常简洁,本身就是一个1万多行的tcl脚本写成的.gitk的代码已经和Git的代码放在同一 ...

  7. IAR配置ICF到项目的实现方法

    以STM8为例: 将项目使用的MCU型号的icf文件拷贝到项目里面,icf一般放在 C:\Program Files\IAR Systems\Embedded Workbench 6.5\stm8\c ...

  8. Struts2---数据封装机制

    Struts2属性驱动和模型驱动 自动完成了数据的获取和封装 LoginAction.java public class LoginAction implements ModelDriven<U ...

  9. nodejs基础1

    nodejs学习网站: https://github.com/alsotang/node-lessons 1.全局对象 (1)node中没有window对象,有global对象替代window对象 g ...

  10. Qsys配置生成nios系统模块

    1. 本次使用的是别人写好的例程,主要研究学习,使用quartus 11打开工程 2. bdf文件是块编辑器的,相当于原理图,以前只在用NIOS的时候会用到这种方式.接下来新建一个工程,添加原理图元件 ...