题面

Bzoj

洛谷

题解

首先把最短路径树建出来(用$Dijkstra$,没试过$SPFA$$\leftarrow$它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我们用点分治来做(滑稽)。

有一点要说,这一题数据比较水,如果不用字典序的话,也可以过。如何建立字典序呢?其实我们从$1$号节点开始遍历路径树(不是最短路径树),令一个点的第一关键字是点权,如果点权相等就按照编号大小为第二关键字,维护一个二元组就好了。

点分治时记两个数组$S[i]$和$num[i]$,表示经过$i$个点的路径最大是多少以及在这个情况下有多少条路径。

之前找重心调了好久。

  1. #include <cmath>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <queue>
  6. #include <iostream>
  7. using std::pair; using std::sort;
  8. using std::priority_queue;
  9. using std::vector; using std::greater;
  10. typedef long long ll;
  11. typedef pair<int, int> pii;
  12. template<typename T>
  13. void read(T &x) {
  14. int flag = 1; x = 0; char ch = getchar();
  15. while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
  16. while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
  17. }
  18. const int N = 3e4 + 10, Inf = 1 << 30;
  19. int n, m, k, from[N], dist[N], MX, tot;
  20. int cnt, to[N << 1], nxt[N << 1], dis[N << 1];
  21. bool vis[N];
  22. vector<pii> G[N]; priority_queue< pii, vector<pii>, greater<pii> > q;
  23. void addEdge(int u, int v, int w) {
  24. to[++cnt] = v, nxt[cnt] = from[u], dis[cnt] = w, from[u] = cnt;
  25. }
  26. void dijk(int s) {
  27. memset(dist, 0x7777777f, sizeof dist);
  28. dist[s] = 0, q.push((pii){0, s});
  29. while(q.size()) {
  30. int u = q.top().second; q.pop();
  31. if(vis[u]) continue; vis[u] = true;
  32. for(int i = 0; i < G[u].size(); ++i) {
  33. int v = G[u][i].first, w = G[u][i].second + dist[u];
  34. if(dist[v] > w) dist[v] = w, q.push((pii){dist[v], v});
  35. }
  36. }
  37. }
  38. void init(int u) {
  39. vis[u] = 1;
  40. for(int i = 0; i < G[u].size(); ++i) {
  41. int v = G[u][i].first, w = G[u][i].second;
  42. if(vis[v] || w + dist[u] != dist[v]) continue;
  43. addEdge(u, v, w), addEdge(v, u, w), init(v);
  44. }
  45. }
  46. int Size, tmp, p, siz[N], maxnow, S[N], num[N];
  47. inline void upt(int &a, int b) { if(a < b) a = b; }
  48. void getrt(int u, int f) {
  49. int max_part = 0; siz[u] = 1;
  50. for(int i = from[u]; i; i = nxt[i]) {
  51. int v = to[i]; if(vis[v] || v == f) continue;
  52. getrt(v, u); siz[u] += siz[v];
  53. upt(max_part, siz[v]);
  54. } upt(max_part, Size - siz[u]);
  55. if(max_part < tmp) p = u, tmp = max_part;
  56. }
  57. void calc(int u, int f, int now) {
  58. upt(maxnow, now);
  59. if(now == k - 1) {
  60. if(dist[u] == MX) ++tot;
  61. else if(dist[u] > MX) MX = dist[u], tot = 1;
  62. return ;
  63. }
  64. int nowans = -1;
  65. if(S[k - 1 - now] != -1) nowans = dist[u] + S[k - 1 - now];
  66. if(nowans == MX) tot += num[k - 1 - now];
  67. else if(nowans > MX) MX = nowans, tot = num[k - 1 - now];
  68. for(int i = from[u]; i; i = nxt[i]) {
  69. int v = to[i]; if(vis[v] || v == f) continue;
  70. dist[v] = dist[u] + dis[i], calc(v, u, now + 1);
  71. }
  72. }
  73. void update(int u, int f, int now) {
  74. if(now == k - 1) return ;
  75. if(S[now] == dist[u]) ++num[now];
  76. else upt(S[now], dist[u]), num[now] = 1;
  77. for(int i = from[u]; i; i = nxt[i]) {
  78. int v = to[i]; if(vis[v] || v == f) continue;
  79. update(v, u, now + 1);
  80. }
  81. }
  82. void doit(int x) {
  83. p = 0, tmp = Inf, getrt(x, 0), vis[p] = 1, maxnow = 0;
  84. for(int i = from[p]; i; i = nxt[i]) {
  85. int v = to[i]; if(vis[v]) continue;
  86. dist[v] = dis[i], calc(v, p, 1), update(v, p, 1);
  87. }
  88. for(int i = 1; i <= maxnow; ++i) S[i] = -1, num[i] = 0;
  89. for(int i = from[p]; i; i = nxt[i]) {
  90. int v = to[i]; if(vis[v]) continue;
  91. Size = siz[v], doit(v);
  92. }
  93. }
  94. int main () {
  95. read(n), read(m), read(k);
  96. for(int i = 1, u, v, w; i <= m; ++i) {
  97. read(u), read(v), read(w);
  98. G[u].push_back((pii){v, w});
  99. G[v].push_back((pii){u, w});
  100. }
  101. for(int i = 1; i <= n; ++i) sort(G[i].begin(), G[i].end());
  102. dijk(1), memset(vis, 0, sizeof vis), init(1);
  103. Size = n, memset(vis, 0, sizeof vis);
  104. memset(dist, 0, sizeof dist), doit(1);
  105. printf("%d %d\n", MX, tot);
  106. return 0;
  107. }

Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)的更多相关文章

  1. (持续更新)虚树,KD-Tree,长链剖分,后缀数组,后缀自动机

    真的就是讲课两天,吸收一个月呢! \(1.\)虚树 \(2.\)KD-Tree \(3.\)长链剖分 \(4.\)后缀数组 后缀数组 \(5.\)后缀自动机 后缀自动机

  2. 树链剖分 (求LCA,第K祖先,轻重链剖分、长链剖分)

      2020/4/30   15:55 树链剖分是一种十分实用的树的方法,用来处理LCA等祖先问题,以及对一棵树上的节点进行批量修改.权值和查询等有奇效. So, what is 树链剖分? 可以简单 ...

  3. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  4. 【BZOJ2830/洛谷3830】随机树(动态规划)

    [BZOJ2830/洛谷3830]随机树(动态规划) 题面 洛谷 题解 先考虑第一问. 第一问的答案显然就是所有情况下所有点的深度的平均数. 考虑新加入的两个点,一定会删去某个叶子,然后新加入两个深度 ...

  5. [FJOI2014]最短路径树问题 长链剖分

    [FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...

  6. Luogu2993 FJOI2014 最短路径树问题 最短路树、长链剖分

    传送门 强行二合一最为致命 第一问直接最短路+$DFS$解决 考虑第二问,与深度相关,可以考虑长链剖分. 设$f_{i,j}$表示长度为$i$,经过边数为$j$时的最大边权和,考虑到每一次从重儿子转移 ...

  7. 洛谷 P4292 - [WC2010]重建计划(长链剖分+线段树)

    题面传送门 我!竟!然!独!立!A!C!了!这!道!题!incredible! 首先看到这类最大化某个分式的题目,可以套路地想到分数规划,考虑二分答案 \(mid\) 并检验是否存在合法的 \(S\) ...

  8. BZOJ.3653.谈笑风生(长链剖分/线段树合并/树状数组)

    BZOJ 洛谷 \(Description\) 给定一棵树,每次询问给定\(p,k\),求满足\(p,a\)都是\(b\)的祖先,且\(p,a\)距离不超过\(k\)的三元组\(p,a,b\)个数. ...

  9. BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)

    题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...

随机推荐

  1. UVA 1640 The Counting Problem

    https://vjudge.net/problem/UVA-1640 题意:统计区间[l,r]中0——9的出现次数 数位DP 注意删除前导0 #include<cmath> #inclu ...

  2. MyBatis框架的使用及源码分析(四) 解析Mapper接口映射xml文件

    在<MyBatis框架中Mapper映射配置的使用及原理解析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder> 一文中,我们知道mybat ...

  3. javascript 访问cookie信息

    在Javascript脚本里,一个cookie 实际就是一个字符串属性.当你读取cookie的值时,就得到一个字符串,里面当前WEB页使用的所有cookies的名称和值.每个cookie除了 name ...

  4. Redis 键值数据类型及基本操作

    到目前为止,Redis 支持的键值数据类型如下: 字符串(String) 哈希(Map) 列表(list) 集合(sets) 有序集合(sorted sets)   1. String 字符串类型 s ...

  5. 【poj2464】树状数组

    这道题..太特么多细节了.. 题意:在平面直角坐标系中给你N个点,stan和ollie玩一个游戏,首先stan在竖直方向上画一条直线,该直线必须要过其中的某个点,然后ollie在水平方向上画一条直线, ...

  6. 【BZOJ4884】太空猫 [DP]

    太空猫 Time Limit: 1 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 太空猫(SpaceCat)是一款画面精 ...

  7. Gradle编译时下载依赖失败解决方法

    如果Gradle在编译的时候没有在本地仓库中发现依赖,就会从远程仓库中下载,默认的远程仓库为mavenCentral(),也就是http://repo1.maven.org/maven2/,但是往往访 ...

  8. Vue前端开发规范(山东数漫江湖)

    一.强制 1. 组件名为多个单词 组件名应该始终是多个单词的,根组件 App 除外. 正例: export default { name: 'TodoItem', // ... } 反例: expor ...

  9. 大聊Python----通过Socket实现简单的ssh客户端

    光只是简单的发消息.收消息没意思,干点正事,可以做一个极简版的ssh,就是客户端连接上服务器后,让服务器执行命令,并返回结果给客户端. #ssh_client.py import socket cli ...

  10. HTML5获取地理位置信息并在Google Maps上显示

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...