题意,给出边和权值,求出两个点间的最短距离。

用离线算法的时候有个地方不知道怎么处理了。在线的本来想用倍增的,但发现倍增算法貌似需要预处理深度而不是权值,不知道怎么处理。套一个rmq的模板吧,用来处理权值的时候。

代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <vector>
  5. using namespace std;
  6.  
  7. const int NN=100010;
  8.  
  9. int n,m;
  10. vector<pair<int,int> > edge[NN],qe[NN];
  11. vector<int> q1,q2;
  12.  
  13. int p[NN];
  14. int find(int x)
  15. {
  16. if (p[x]!=x) p[x]=find(p[x]);
  17. return p[x];
  18. }
  19.  
  20. int sum=0,ans[NN],dis[NN];
  21. bool vis[NN]={0};
  22. void lca(int u,int fa)
  23. {
  24. p[u]=u;
  25. for (int i=0; i<edge[u].size(); i++)
  26. {
  27. int v=edge[u][i].first;
  28. if (v==fa) continue;
  29. dis[v]=dis[u]+edge[u][i].second;
  30. lca(v,u);
  31. p[v]=u;
  32. }
  33. vis[u]=true;
  34. if (sum==m) return;
  35. for (int i=0; i<qe[u].size(); i++)
  36. {
  37. int v=qe[u][i].first;
  38. if (vis[v])
  39. ans[qe[u][i].second]=dis[u]+dis[v]-2*dis[find(v)];
  40. }
  41. }
  42.  
  43. int main()
  44. {
  45. int u,v,w;
  46. char str[4];
  47. scanf("%d%d",&n,&m);
  48. for (int i=1; i<=n; i++)
  49. {
  50. edge[i].clear();
  51. }
  52. for (int i=1; i<=m; i++)
  53. {
  54. scanf("%d%d%d%s",&u,&v,&w,str);
  55. edge[u].push_back(make_pair(v,w));
  56. edge[v].push_back(make_pair(u,w));
  57. }
  58. scanf("%d",&m);
  59. for (int i=0; i<m; i++)
  60. {
  61. scanf("%d%d",&u,&v);
  62. qe[u].push_back(make_pair(v,i));
  63. qe[v].push_back(make_pair(u,i));
  64. ans[i]=0;
  65. }
  66. dis[1]=0;
  67. lca(1,0);
  68. for (int i=0; i<m; i++) printf("%d\n",ans[i]);
  69. return 0;
  70. }

在线的dfs+rmq模板套一个:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <cmath>
  5. #include <vector>
  6. using namespace std;
  7.  
  8. const int NN=50000;
  9.  
  10. int n,rt;
  11. vector<pair<int,int> > edge[NN];
  12.  
  13. int depth=0;
  14. int bn=0,b[NN*2]; //深度序列
  15. int f[NN*2]; //对应深度序列中的结点编号
  16. int p[NN]; //结点在深度序列中的首位置
  17. int dis[NN]; //结点到根的距离
  18. void dfs(int u,int fa)
  19. {
  20. int tmp=++depth;
  21. b[++bn]=tmp; f[tmp]=u; p[u]=bn;
  22. for (int i=0; i<edge[u].size(); i++)
  23. {
  24. int v=edge[u][i].first;
  25. if (v==fa) continue;
  26. dis[v]=dis[u]+edge[u][i].second;
  27. dfs(v,u);
  28. b[++bn]=tmp;
  29. }
  30. }
  31.  
  32. int dp[NN*2][20];
  33. void rmq_init(int n) //以深度序列做rmq
  34. {
  35. for (int i=1; i<=n; i++) dp[i][0]=b[i];
  36. int m=floor(log(n*1.0)/log(2.0));
  37. for (int j=1; j<=m; j++)
  38. for (int i=1; i<=n-(1<<j)+1; i++)
  39. dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
  40. }
  41. int rmq(int l,int r)
  42. {
  43. int k=floor(log((r-l+1)*1.0)/log(2.0));
  44. return min(dp[l][k],dp[r-(1<<k)+1][k]);
  45. }
  46.  
  47. int lca(int a,int b)
  48. {
  49. if (p[a]>p[b]) swap(a,b);
  50. int k=rmq(p[a],p[b]);
  51. return f[k];
  52. }
  53.  
  54. int main()
  55. {
  56. int m,u,v,w;
  57. char str[4];
  58. scanf("%d%d",&n,&m);
  59. for (int i=1; i<=n; i++) edge[i].clear();
  60. while (m--)
  61. {
  62. scanf("%d%d%d%s",&u,&v,&w,str);
  63. edge[u].push_back(make_pair(v,w));
  64. edge[v].push_back(make_pair(u,w));
  65. }
  66. rt=1; dis[rt]=0;
  67. dfs(1,0);
  68. rmq_init(bn);
  69. scanf("%d",&m);
  70. while (m--)
  71. {
  72. scanf("%d%d",&u,&v);
  73. printf("%d\n",dis[u]+dis[v]-2*dis[lca(u,v)]);
  74. }
  75. return 0;
  76. }

poj 1986LCA离线dfs+并查集的更多相关文章

  1. 【bzoj5183】[Baltic2016]Park 离线+对偶图+并查集

    题目描述 在Byteland的首都,有一个矩形围栏围起来的公园.在这个公园里树和访客都以一个圆形表示.公园有四个出入口,每个角落一个(1=左下角,2=右下角,3=右上角,4=左上角).访客能通过这些出 ...

  2. POJ 1562 Oil Deposits (并查集 OR DFS求联通块)

    Oil Deposits Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14628   Accepted: 7972 Des ...

  3. 距离LCA离线算法Tarjan + dfs + 并查集

    距离B - Distance in the Tree 还是普通的LCA但是要求的是两个节点之间的距离,学到了一些 一开始我想用带权并查集进行优化,但是LCA合并的过程晚于离线计算的过程,所以路径长度会 ...

  4. HDU 5441 离线处理 + 并查集

    题意:给n个节点m条带权值边的无向图.然后q个问题,每次询问点对的数目,点对需要满足的条件是:1)连通:2)其路径的最大权值不能超过询问值. 分析:如果没次询问一次,dfs一次,很可能超时,因此可以用 ...

  5. poj 1733(带权并查集+离散化)

    题目链接:http://poj.org/problem?id=1733 思路:这题一看就想到要用并查集做了,不过一看数据这么大,感觉有点棘手,其实,我们仔细一想可以发现,我们需要记录的是出现过的节点到 ...

  6. poj 1182 食物链 (并查集)

    http://poj.org/problem?id=1182 关于并查集 很好的一道题,开始也看了一直没懂.这次是因为<挑战程序设计竞赛>书上有讲解看了几遍终于懂了.是一种很好的思路,跟网 ...

  7. POJ 1182 食物链(并查集拆点)

    [题目链接] http://poj.org/problem?id=1182 [题目大意] 草原上有三种物种,分别为A,B,C A吃B,B吃C,C吃A. 1 x y表示x和y是同类,2 x y表示x吃y ...

  8. 分珠(dfs+并查集)

    1140 分珠 时间限制:500MS  内存限制:65536K提交次数:24 通过次数:18 题型: 编程题   语言: G++;GCC Description 如下图所示,有若干珠子,每颗珠子重量不 ...

  9. Codeforces 1027D Mouse Hunt (强连通缩点 || DFS+并查集)

    <题目链接> 题目大意: 有n个房间,每个房间都会有一只老鼠.处于第i个房间的老鼠可以逃窜到第ai个房间中.现在要清理掉所有的老鼠,而在第i个房间中防止老鼠夹的花费是ci,问你消灭掉所有老 ...

随机推荐

  1. 43. leetcode 459. Repeated Substring Pattern

    459. Repeated Substring Pattern Given a non-empty string check if it can be constructed by taking a ...

  2. amd和cmd区别

    作者:玉伯 链接:https://www.zhihu.com/question/20351507/answer/14859415 来源:知乎 著作权归作者所有,转载请联系作者获得授权. AMD 是 R ...

  3. Python Socket 简单聊天室2

    上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  4. 【思维】【水】 南阳oj 喷水装置(一)

    描述 现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以它为中心的半径为实数Ri(0<Ri<15)的圆被湿润,这有充足的喷水装置i(1& ...

  5. ECharts的简单使用

    ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖轻 ...

  6. NOIP 2002 提高组 字串变换

    题目描述 已知有两个字串 A, B 及一组字串变换的规则(至多6个规则): A1 -> B1 A2 -> B2 规则的含义为:在 A$中的子串 A1 可以变换为 B1.A2 可以变换为 B ...

  7. 关于Spring总结

    关于Spring总结 Spring引入 传统的基于mvc的项目框架结构:Entity / dao / service / action 简单用户访问流程:/user.action ----> T ...

  8. 关于 Overtrue 的拼音库 overtrue/pinyin 为何 travis 为 error【社交系统研发日记十】

    什么是ThinkSNS ? ThinkSNS(简称TS),一款全平台综合性社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案,目前最新版本为ThinkSNS+(简称TS+).社交系统 ...

  9. python ——面向对象进阶

    1.staticmethod和classmethod staticmethod  静态方法: 让类里的方法,直接被类调用,就像正常的函数一样 宝宝,男 博博,女 海娇,男 海燕,女 海东,男 海峰,男 ...

  10. 集合set

    一.集合的作用 知识点回顾:可变类型是不可hash类型,不可变类型是可hash类型 作用:去重,关系运算 定义:可以包含多个元素,用逗号分割,集合的元素遵循三个原则: 1.每个元素必须是不可变类型(可 ...