题目链接


解题思路:

首先我们知道最小路径树实际上就是Dijkstra算法在找最短路的时候转移的过程就是一个最短路径树。

那么我们就可以先跑个最短路,记录一下各个最短路的路径。然后就是很裸的点分治。分治根节点,枚举每个子树和前面统计过的子树的贡献,计算完一个子树后,更新每个深度下的最长路径,以及路径条数。

但是这个题目问的有问题,实际上它那个路径条数是在K的限制下的条数。

坑点:
1.就是对于分治时候枚举子树的时候,他可以直接从分治的root连到子树,不需要其他子树,也就是deepth==k−1deepth == k - 1deepth==k−1的情况。
2.就是在更新答案的时候我们还要判断一下这个深度的结点是否存在?。


#include <bits/stdc++.h>using namespace std;
typedef long long ll;
const int maxn = 6e4 + 10;
struct node {int nxt, to, w;
}edge[maxn<<1],edge1[maxn<<1];
int head[maxn],head1[maxn], cnt = 1, cnt1 = 1;
inline void add(int from, int to, int val) {//建图edge[++cnt] = {head[from],to,val};head[from] = cnt;
}
inline void add1(int from, int to, int val) {//建最小路径树edge1[++cnt1] = {head1[from],to,val};head1[from] = cnt1;
}
int n, m, k;
//.......... 点分治
bool vis[maxn];
int MX, root, max_son[maxn], now_num ,siz[maxn];
void getroot(int u, int fa) {max_son[u] = 0;siz[u] = 1; for(int i = head1[u]; i; i = edge1[i].nxt) {int v = edge1[i].to;if(v == fa || vis[v]) continue;getroot(v,u);siz[u] += siz[v];max_son[u] = max(max_son[u],siz[v]);}max_son[u] = max(max_son[u],now_num - siz[u]);if(max_son[u] < MX) MX = max_son[u], root = u;
}
int kpath, Count;
pair<int,int> maxk[maxn];//长度为i的最长路径的长度,以及条数
int maxdep;
void dfs(int u, int fa, int dep, int len) {maxdep = max(maxdep,dep);if(dep == k - 1) {//在自己子树进行统计 特判if(len == kpath) Count ++;else if(len > kpath){kpath = len;Count = 1;}return;}//maxk[k-dep-1].first == 0 说明没有这个点if(maxk[k-dep-1].first && kpath < maxk[k-dep-1].first + len) {kpath = maxk[k-dep-1].first + len;Count = maxk[k-dep-1].second;} else if(maxk[k-dep-1].first && kpath == maxk[k-dep-1].first + len)Count += maxk[k-dep-1].second;for(int i = head1[u]; i; i = edge1[i].nxt) {int v = edge1[i].to;if(vis[v] || v == fa) continue;dfs(v,u,dep+1,len+edge1[i].w);}
}void dfs1(int u, int fa, int dep, int len) {if(maxk[dep].first < len) maxk[dep] = {len,1};else if(maxk[dep].first == len) maxk[dep].second++;for(int i = head1[u]; i; i = edge1[i].nxt) {int v = edge1[i].to;if(vis[v] || v == fa) continue;dfs1(v,u,dep+1,len+edge1[i].w);}
}inline void getans(int u) {maxdep = 0;for(int i = head1[u]; i; i = edge1[i].nxt) {int v = edge1[i].to;if(vis[v]) continue;dfs(v,u,1,edge1[i].w);dfs1(v,u,1,edge1[i].w);}for(int i = 0; i <= maxdep; ++ i)maxk[i] = {0,0};
}void Div(int u) {vis[u] = 1;getans(u);for(int i = head1[u]; i; i = edge1[i].nxt) {int v = edge1[i].to;if(vis[v]) continue;MX = 1e9, root = 0;now_num = siz[v];getroot(v,u);Div(root);}
}//..................................
int dist[maxn];
pair<int,int> path[maxn];
bool f[maxn];
void Dij(int start) {memset(dist,0x3f,sizeof(dist));dist[start] = 0;priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>> > q;q.push((pair<int,int>){0,start});while(!q.empty()) {auto top = q.top();q.pop();if(f[top.second]) continue;f[top.second] = true;for(int i = head[top.second]; i; i = edge[i].nxt) {int v = edge[i].to;if(dist[v] > dist[top.second] + edge[i].w) {path[v] = {top.second,edge[i].w};dist[v] = dist[top.second] + edge[i].w;q.push((pair<int,int>){dist[v],v});}}}
}void build() {for(int i = 1; i <= n; ++ i) if(path[i].first) {add1(i,path[i].first,path[i].second);add1(path[i].first,i,path[i].second);}
}//................................
int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);//.........cin >> n >> m >> k;for(int i = 0; i < m; ++ i) {int u, v, w;cin >> u >> v >> w;add(u,v,w);add(v,u,w);}Dij(1);build();now_num = n, MX = 1e9, root = 0;getroot(1,0);Div(root);cout << kpath << " " << Count << "\n";return 0;}

点分治问题 ----------- P2993 [FJOI2014]最短路径树问题 [最短路径树+点分治+采坑]相关推荐

  1. 【BJOI2017】树的难题【点分治】【线段树】

    传送门 传送门 题意:给一棵树,树上有颜色,每种颜色有权值,定义一条路径的权值为所有颜色相同段的权值之和,求长度在[L,R][L,R][L,R]中的路径的最大权值. 数据范围:暴力过不了 显然是个点分 ...

  2. CDQ分治(二维CDQ 、三维CDQ+树状数组、四维CDQ+CDQ+树状数组)

    CDQ分治 CDQ分治相较于普通分治,多了左区间处理后对于右区间的影响. 利用这一点,CDQ分治可以用来做很多数据结构的题目(树状数组.线段树),加一个log的时间复杂度来优化一维. 操作: 假设有两 ...

  3. 浅谈树形结构的特性和应用(上):多叉树,红黑树,堆,Trie树,B树,B+树......

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 上篇文章我们主要介绍了线性数据结构,本篇233酱带大家看看 无所不 ...

  4. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释...

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  5. 最短路径生成树计数+最短路径生成树

    最短路径生成树计数. 我们应该先明白什么是最短路径生成树,不会戳这里. 计数方法明显是要使用乘法原理计数,也就是说我们可以得出每一步的方案数再乘进答案中. 接下来考虑如何的出每一步的方案数,所谓方案数 ...

  6. 二叉排序树、平衡二叉树、红黑树、B树、B+树

    全民制作人们,大家好.我是练习时长两天半的个人练习册,喜欢B树 ,B+树, BST树, AVL树,来 red black  ~ 目录 一.二叉排序树(BST树) 1.1二叉排序树的定义 1.2二叉排序 ...

  7. 种树:二叉树、二叉搜索树、AVL树、红黑树、哈夫曼树、B树、树与森林

    虽然今天不是植树节,但是我今天想种树. 文章目录 树,什么是树? 二叉树 定义 二叉树的创建 二叉树的前中后序遍历 前序遍历: 中序遍历 后序遍历 已知前序.中序遍历结果,还原二叉树 已知后序.中序遍 ...

  8. 浅谈树形结构的特性和应用(上):多叉树,红黑树,堆,Trie树,B树,B+树...

    上篇文章我们主要介绍了线性数据结构,本篇233酱带大家康康 无所不在的非线性数据结构之一:树形结构的特点和应用. 树形结构,是指:数据元素之间的关系像一颗树的数据结构.我们看图说话: 它具有以下特点: ...

  9. 【数据结构与算法图文动画详解】终于可以彻底弄懂:红黑树、B-树、B+树、B*树、满二叉树、完全二叉树、平衡二叉树、二叉搜索树...

    1.树简介 1.1基本概念 树是由结点或顶点和边组成的(可能是非线性的)且不存在着任何环的一种数据结构.没有结点的树称为空(null或empty)树.一棵非空的树包括一个根结点,还(很可能)有多个附加 ...

最新文章

  1. 中国无人车公司AutoX,打响加州RoboTaxi服务第一枪
  2. ps命令显示uid而不是用户名的解决方法
  3. c#进行三角形周长面积计算公式_小学数学,期末复习,量的计算单位及进率归类,常用计算公式表...
  4. tableau中文版教程pdf_PDF 文件
  5. [UWP]本地化入门
  6. mybatis之trim prefix= suffix= suffixOverrides= prefixOverrides=/trim
  7. 谁更了解你,是女朋友吗。不,是这些推荐算法。
  8. linux 命令api,linux命令行下字典,使用有道API
  9. leetcode204. 计数质数(vip题)
  10. SaaS 中 6 种常见 UI 入职模式
  11. 不是计算机专业及其相关专业,对软件编程一窍不通,能学好编程吗?
  12. 常数中有换行符的错误
  13. 转-PHP 设计模式 之策略模式 应用场景 Strategy Pattern
  14. cdrx4自动排版步骤_教你用CorelDRAW X4轻松排出干净整齐段落
  15. 浅谈 Java 24个设计模式(23个GoF设计模式 + 简单工厂模式) 之 六个创建型模式...
  16. (wa待对拍)HDU - 2057 十六进制加法 难度:C++入门 复杂度:有点复杂 翻译难度:简单...
  17. 海量大数据地图可视化
  18. oracle+not+logged+on,sqlplus ORA-01012: not logged on
  19. android 9.0 Launcher3去掉默认的google搜索栏
  20. 批量论文自动下载——从dblp数据库中查找并爬取论文

热门文章

  1. 虚拟机CENTOS7下 安装8.0版本MySQL MySQL主从配置详细~
  2. 实战|基于图割算法的木材表面缺陷图像分析
  3. PanoNet3D:一种3D目标检测方法
  4. 通过对比对象掩码建议的无监督语义分割
  5. 微软开源: 老旧照片修复的AI算法
  6. java调用PageOffice生成word
  7. 糟糕的css用法 1
  8. Ferris教程学习笔记:js示例2.13 简易JS年历
  9. vs2008断点上出现感叹号解决办法
  10. 搞死了 报错【libc-client.a: could not read symbols: ...