HYSBZ - 4016 最短路径树问题 点分治 + 最短路径最小字典序
题解:首先对于给定的图,需要找到那些从1好点出发然后到x号点的最短路, 如果有多条最短路就要找到字典序最小的路,这样扣完这些边之后就会有一棵树。然后再就是很普通的点分治了。
对于扣边这个问题, 我们先跑一遍最短路,这样就可以得到1号点到其他的点的距离。
然后在跑一遍dfs, 我们在跑dfs找路的时候, 可以通过 d[u] + ct[i] == d[v] 来判断是不是最短路是否可以走这条边, 然后我们再从所有可能边中的最小编号出发,这样我们就能保证字典序最小了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = (int)1e9+;
const int N = 3e4 + ;
vector<pll> vc[N];
int d[N];
void dij(){
memset(d, inf, sizeof(d));
priority_queue<pll, vector<pll>, greater<pll> > q;
d[] = ;
q.push(pll(,));
int x, dd, v, ct;
while(!q.empty()){
x = q.top().se, dd = q.top().fi;
q.pop();
if(dd != d[x]) continue;
for(int i = ; i < vc[x].size(); ++i){
v = vc[x][i].fi , ct = vc[x][i].se;
if(d[v] > d[x] + ct){
d[v] = d[x] + ct;
q.push(pll(d[v], v));
}
}
}
return;
}
int vis[N];
int head[N], to[N<<], val[N<<], nt[N<<], tot = ;
void add(int u, int v, int ct){
to[tot] = v;
val[tot] = ct;
nt[tot] = head[u];
head[u] = tot++;
return ;
}
void dfs(int u){
vis[u] = ;
int v, dd;
for(int i = ; i < vc[u].size(); i++){
v = vc[u][i].fi, dd = vc[u][i].se;
if(vis[v] || d[v] != d[u] + dd) continue;
add(u, v, dd);
add(v, u, dd);
dfs(v);
}
return ;
}
int sz[N];
int rt, minval;
int n, m, k;
void get_rt(int o, int u, int num){
sz[u] = ;
int v;
int maxval = ;
for(int i = head[u]; ~i; i = nt[i]){
v = to[i];
if(v == o || vis[v]) continue;
get_rt(u, v, num);
sz[u] += sz[v];
maxval = max(maxval, sz[v]);
}
if(o) maxval = max(maxval, num - sz[u]);
if(maxval < minval){
minval = maxval;
rt = u;
}
}
int fans = , fcnt = ;
int cnt[N], dis[N];
void Update(int vval, int num){
if(fans == vval) fcnt += num;
else if(fans < vval) fans = vval, fcnt = num;
return ;
}
void Dfs(int o, int u, int w, int num){
sz[u] = ;
if(num == k-)
Update(w, );
if(k >= num && dis[k-num]){
Update(w+dis[k-num], cnt[k-num]);
}
for(int i = head[u]; ~i; i = nt[i]){
int v = to[i];
if(v == o || vis[v]) continue;
Dfs(u, v,w+val[i], num+);
sz[u] += sz[v];
}
return ;
}
void Change(int o, int u, int w, int num, int op){
if(num >= k) return ;
if(op == ) {
if(dis[num+] < w) dis[num+] = w, cnt[num+] = ;
else if(dis[num+] == w) cnt[num+]++;
}
else dis[num+] = cnt[num+] = ;
for(int i = head[u]; ~i; i = nt[i]){
int v = to[i];
if(v == o || vis[v]) continue;
Change(u, v, w+val[i], num+, op);
}
return ;
}
void solve(int x, int num){
if(num <= ) return ;
minval = inf;
get_rt(, x, num);
vis[rt] = ;
int v;
for(int i = head[rt]; ~i; i = nt[i]){
v = to[i];
if(vis[v]) continue;
Dfs(, v, val[i], );
Change(, v, val[i], , );
}
for(int i = head[rt]; ~i; i = nt[i]){
v = to[i];
if(vis[v]) continue;
Change(, v, val[i], , );
}
for(int i = head[rt]; ~i; i = nt[i]){
v = to[i];
if(vis[v]) continue;
solve(v, sz[v]);
}
return ;
}
int main(){
int u, v, w;
memset(head, -, sizeof(head));
scanf("%d%d%d", &n, &m, &k);
for(int i = ; i <= m; i++){
scanf("%d%d%d", &u, &v, &w);
vc[u].pb(pll(v,w));
vc[v].pb(pll(u,w));
}
dij();
dfs();
memset(vis, , sizeof(vis));
solve(, n);
printf("%d %d", fans, fcnt);
return ;
}
HYSBZ - 4016 最短路径树问题 点分治 + 最短路径最小字典序的更多相关文章
- BZOJ 4016 最短路径树问题 最短路径树构造+点分治
题目: BZOJ4016最短路径树问题 分析: 大家都说这是一道强行拼出来的题,属于是两种算法的模板题. 我们用dijkstra算法算出1为源点的最短路数组,然后遍历一下建出最短路树. 之后就是裸的点 ...
- P2993 [FJOI2014]最短路径树问题 点分治+最短路
这道题还是非常简单的,由于我们要保证最小字典序,因此我们需要把边进行排序,然后从大到小插入,因为链式前向星是倒着存的.我们只需要先跑一个最短路,然后查询边是不是在最短路上,这个可以通过枚举边并用 di ...
- 【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治
题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...
- bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 426 Solved: 147[Submit][Stat ...
- 【BZOJ-4016】最短路径树问题 Dijkstra + 点分治
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1092 Solved: 383[Submit][Sta ...
- [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1796 Solved: 625[Submit][Sta ...
- bzoj 4016: [FJOI2014]最短路径树问题
bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...
- HDU4871 Shortest-path tree(最短路径树 + 树的点分治)
题目大概要先求一张边有权的图的根为1的最短路径树,要满足根到各点路径序列的字典序最小:然后求这棵最短路径树包含k个结点的最长路径的长度和个数. 首先先构造出这棵字典序最小的最短路径树..好吧,我太傻逼 ...
- BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治
BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择 ...
随机推荐
- 【Android Studio】使用 Genymotion 调试出现错误 INSTALL_FAILED_CPU_ABI_INCOMPATI
RT -- 解决方法参考: https://my.oschina.net/u/242764/blog/375909 http://blog.csdn.net/wjr2012/article/detai ...
- 【Algorithm】二分查找(递归实现)
二分查找(递归实现),Java 代码如下: public class BinarySearch { public static int rank(int key, int[] a) { return ...
- openGL基本概念
OpenGL自身是一个巨大的状态机(State Machine):一系列的变量描述OpenGL此刻应当如何运行.OpenGL的状态通常被称为OpenGL上下文(Context).我们通常使用如下途径去 ...
- 【Java例题】8.2 手工编写字符串统计的可视化程序
2. 手工编写字符串统计的可视化程序. 一个Frame窗体容器,布局为null,两个TextField组件,一个Button组件. Button组件上添加ActionEvent事件监听器Actio ...
- 关于 IntelliJ 的 IDEA PyCharm 等更新 2019.2 后中文乱码 的解决方案
关于IntelliJ 的2019.2 更新后的中文乱码解决方案 设置 备用字体 file -> Setting -> Editor ->Font 由于编程常用英文首选字体font默认 ...
- 2019最新最全Java开发面试常见问题答案总结
2019最新最全Java开发面试常见问题答案总结 马上准备9月份出去面试Java开发,自己学习丢西瓜捡芝麻,学了的都忘了,所以有机会自己做个学习笔记,摘录自各个博文以及总结. 1.JAVA面向对象的特 ...
- k8s学习笔记
9.deployment:声明式的升级应用 9.1.使用RC实现滚动升级 #kubectl rolling-update kubia-v1 kubia-v2 --image=luksa/kubia:v ...
- lxml解析网页
目录 1. 什么是lxml 2. 初次使用 3. xpath 3.2 标签定位 3.3 序列定位 3.4 轴定位 4. 实例 1. 什么是lxml lxml是干什么的?简单的说来,lxml是帮助我们解 ...
- CSV Data Set Config 拓展开发
1.目的 在日常的性能测试项目中,经常会遇到参数化的问题,我们所熟知的LR工具对参数化支持非常友好,然而JMeter相对逊色一些.大家都知道在使用JMeter工具参数化时常用CSV Data Set ...
- Docker 方式部署 Solo 博客系统总结
此篇为Docker部署方式,另有Tomcat部署方式,请参考文章<Tomcat 方式部署 Solo 博客系统总结> 最近搭建了一个博客系统,作为自己的主页,方便记录一些平时所见所闻 ...