题目链接:

https://codeforces.com/contest/1051/problem/F

题目大意:

给出一张$n$个点,$m$条边的带权无向图,多次询问,每次给出$u,v$,要求输出$u$到$v$的最短距离

$1<=n<=m<=10^5,m-n<=20$

题解:

显然我们要从$m-n<=20$入手,发现这张图非常的稀疏,所以按照套路我们先随便搞一棵生成树(和kruskal的步骤差不多只是去掉了排序)。

当询问两个点$u,v$的最短距离时我们先只考虑树上的点,显然我们可以预处理出到根节点的距离$O(qlogn)$的搞。

然后考虑非树边,我们称非树边的端点为特殊点,特殊点的个数小于等于40,显然不在树上的最短路径肯定至少经过一个特殊点,所以我们对每个特殊点跑一次dijkstra,然后每次再枚举一下特殊点更新答案即可

  1. #include<algorithm>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<iostream>
  5. #include<vector>
  6. #include<set>
  7. #include<queue>
  8. using namespace std;
  9. typedef long long ll;
  10.  
  11. const int N=2e5+;
  12. const ll inf=1e17;
  13. int n,m,tot,k;
  14. int u[N],v[N],tmp[N],fa[N][],f[N],head[N],d[N];
  15. ll dd[][N],dep[N],w[N];
  16. struct EDGE
  17. {
  18. int to,nxt;ll w;
  19. }edge[N<<];
  20. struct NODE
  21. {
  22. int to;ll w;
  23. };
  24. vector <NODE> g[N];
  25. set <int> p;
  26. struct node
  27. {
  28. int now;ll dis;
  29. };
  30. bool operator < (node x,node y) {return x.dis>y.dis;}
  31. inline ll read()
  32. {
  33. char ch=getchar();
  34. ll s=,f=;
  35. while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
  36. while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
  37. return s*f;
  38. }
  39. int find(int x)
  40. {
  41. if (x!=f[x]) f[x]=find(f[x]);
  42. return f[x];
  43. }
  44. void add(int x,int y,ll w)
  45. {
  46. edge[++tot]=(EDGE){y,head[x],w};
  47. head[x]=tot;
  48. }
  49. void dij(int s)
  50. {
  51. ++k;
  52. for (int i=;i<=n;i++) dd[k][i]=inf;
  53. dd[k][s]=;
  54. priority_queue <node> q;
  55. q.push((node){s,});
  56. while (!q.empty())
  57. {
  58. node e=q.top();q.pop();
  59. int now=e.now;
  60. if (dd[k][now]!=e.dis) continue;
  61. for (int i=;i<g[now].size();i++)
  62. {
  63. int y=g[now][i].to;
  64. if (dd[k][y]>dd[k][now]+g[now][i].w)
  65. {
  66. dd[k][y]=dd[k][now]+g[now][i].w;
  67. q.push((node){y,dd[k][y]});
  68. }
  69. }
  70. }
  71. }
  72. void dfs(int x,int pre)
  73. {
  74. for (int i=;i<=;i++)
  75. {
  76. if (d[x]<(<<i)) break;
  77. fa[x][i]=fa[fa[x][i-]][i-];
  78. }
  79. for (int i=head[x];i;i=edge[i].nxt)
  80. {
  81. int y=edge[i].to;
  82. if (y==pre) continue;
  83. fa[y][]=x;
  84. dep[y]=dep[x]+edge[i].w;
  85. d[y]=d[x]+;
  86. dfs(y,x);
  87. }
  88. }
  89. int lca(int x,int y)
  90. {
  91. if (d[x]<d[y]) swap(x,y);
  92. for (int i=;i>=;i--) if (d[fa[x][i]]>=d[y]) x=fa[x][i];
  93. if (x==y) return x;
  94. for (int i=;i>=;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
  95. return fa[x][];
  96. }
  97. int main()
  98. {
  99. n=read();m=read();
  100. for (int i=;i<=m;i++)
  101. {
  102. u[i]=read();v[i]=read();w[i]=read();
  103. g[u[i]].push_back((NODE){v[i],w[i]});
  104. g[v[i]].push_back((NODE){u[i],w[i]});
  105. }
  106. for (int i=;i<=n;i++) f[i]=i;
  107. for (int i=;i<=m;i++)
  108. {
  109. int U=find(u[i]),V=find(v[i]);
  110. if (U!=V)
  111. {
  112. f[U]=V;
  113. tmp[i]=;
  114. }
  115. }
  116. for (int i=;i<=m;i++)
  117. {
  118. if (tmp[i]) {add(u[i],v[i],w[i]);add(v[i],u[i],w[i]);}//printf("qq%d %d\n",u[i],v[i]);
  119. else p.insert(u[i]),p.insert(v[i]);
  120. }
  121. for (set<int>::iterator it=p.begin();it!=p.end();it++) dij((*it));
  122. d[]=-;dfs(,-);
  123. //printf("dd%d\n",fa[2][0]);
  124. int q=read();
  125. while (q--)
  126. {
  127. int x=read(),y=read();
  128. int LCA=lca(x,y);
  129. //printf("LL%d\n",LCA);
  130. ll mi=dep[x]+dep[y]-*dep[LCA];
  131. //printf("LL%lld\n",mi);
  132. for (int i=;i<=k;i++)
  133. {
  134. mi=min(mi,dd[i][x]+dd[i][y]);
  135. }
  136. printf("%lld\n",mi);
  137. }
  138. return ;
  139. }

[Codeforces 1051F] The Shortest Statement 解题报告(树+最短路)的更多相关文章

  1. codeforces 1051F The Shortest Statement

    题目链接:codeforces 1051F The Shortest Statement 题意:\(q\)组询问,求任意两点之间的最短路,图满足\(m-n\leq 20\) 分析:一开始看这道题:fl ...

  2. Codeforces.1051F.The Shortest Statement(最短路Dijkstra)

    题目链接 先随便建一棵树. 如果两个点(u,v)不经过非树边,它们的dis可以直接算. 如果两个点经过非树边呢?即它们一定要经过该边的两个端点,可以直接用这两个点到 u,v 的最短路更新答案. 所以枚 ...

  3. 2018.09.24 codeforces 1051F. The Shortest Statement(dijkstra+lca)

    传送门 这真是一道一言难尽的题. 首先比赛的时候居然没想出来正解. 其次赛后调试一直调不出来最后发现是depth传错了. 其实这是一道简单题啊. 对于树边直接lca求距离. 由于非树边最多21条. 因 ...

  4. Codeforces 1051E Vasya and Big Integers&1051F The Shortest Statement

    1051E. Vasya and Big Integers 题意 给出三个大整数\(a,l,r\),定义\(a\)的一种合法的拆分为把\(a\)表示成若干个字符串首位相连,且每个字符串的大小在\(l, ...

  5. Codeforces Educational Round 92 赛后解题报告(A-G)

    Codeforces Educational Round 92 赛后解题报告 惨 huayucaiji 惨 A. LCM Problem 赛前:A题嘛,总归简单的咯 赛后:A题这种**题居然想了20m ...

  6. Codeforces Round #382 (Div. 2) 解题报告

    CF一如既往在深夜举行,我也一如既往在周三上午的C++课上进行了virtual participation.这次div2的题目除了E题都水的一塌糊涂,参赛时的E题最后也没有几个参赛者AC,排名又成为了 ...

  7. codeforces 476C.Dreamoon and Sums 解题报告

    题目链接:http://codeforces.com/problemset/problem/476/C 题目意思:给出两个数:a 和 b,要求算出 (x/b) / (x%b) == k,其中 k 的取 ...

  8. codeforces 501C. Misha and Forest 解题报告

    题目链接:http://codeforces.com/problemset/problem/501/C 题目意思:有 n 个点,编号为 0 - n-1.给出 n 个点的度数(即有多少个点跟它有边相连) ...

  9. codeforces 507B. Amr and Pins 解题报告

    题目链接:http://codeforces.com/problemset/problem/507/B 题目意思:给出圆的半径,以及圆心坐标和最终圆心要到达的坐标位置.问最少步数是多少.移动见下图.( ...

随机推荐

  1. Centos上JDK的安装搭建

    一.下载 yum search java|grep jdk //查找所有jdk版本 二.选择安装1.8 yum install java-1.8.0-openjdk-src-debug.x86_64 ...

  2. CentOS 安装 PHP 扩展

    下载地址:https://pecl.php.net/package/redis 上传目录:/usr/local/src //安装依赖 yum install php-devel -y //进入安装包目 ...

  3. JSON是什么?为JavaScript准备的数据格式

    JSON是什么?为JavaScript准备的数据格式 还不了解JSON是什么?看了下面这篇文章,您对JSON是什么应该能够有了一个比较清晰的概念. JSON 即 JavaScript. Object ...

  4. Stack Overflow大揭密:哪一种程序员工资最高?

    Stackoverflow在程序员之间可以說是无人不知无人不晓,甚至常有人开玩笑说:“如果stackoverflow倒闭了,全世界代码的产出率将下降一半以上”或许听起来有点夸张,但是不难想像这个网站在 ...

  5. IOS - [UIDevice currentDevice] name/model/localizedMode/systemName/systemVersion...../userInterfaceIdiom

    + (UIDevice *)currentDevice; @property(nonatomic,readonly,retain) NSString    *name;              // ...

  6. [BZOJ3438][洛谷P1361]小M的作物

    题目大意:有A.B两个集合和n个物品,每个物品只能放在一个集合里.每个物品放在不同集合内能获得不同价值.有一些物品,如果它们同时放在一个集合内,则会产生新的价值(A和B中都有且不一定相同(c1和c2) ...

  7. js 对象的创建方式和对象的区别

    js一个有三种方法创建对象,这里做一个总结. 1.对象直接量 所谓对象直接量,可以看做是一副映射表,这个方法也是最直接的一个方法,个人比较建议, 1 2 3 4 5 6 7 8 9 10 11 12 ...

  8. RabbitMQ学习总结(3)——入门实例教程详解

    一.起航 本章节,柯南君将从几个层面,用官网例子讲解一下RabbitMQ的实操经典程序案例,让大家重新回到经典"Hello world!"(The simplest thing t ...

  9. 2015 Multi-University Training Contest 3 hdu 5324 Boring Class

    Boring Class Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  10. javascript-js常用插件集合

    area.js 中国地区分级的js代码  Scripts/crypto.js  CryptoJS (crypto.js) 为 JavaScript 提供了各种各样的加密算法               ...