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出发,往其余所有点分别走一次并返回. 往某一个点走时,选择 ...
随机推荐
- Appium+python自动化(二十六)- 烟花一瞬,昙花一现 -Toats提示(超详解)
简介 今天宏哥在这里首先给小伙伴们和童鞋们分享一个有关昙花的小典故:话说昙花原是一位花神,她每天都开花,四季都灿烂.她还爱上了每天给她浇水除草的年轻人.后来,此事给玉帝得知.于是,玉帝大发雷霆,要拆散 ...
- ansible批量管理服务 下
1 ansible-playbook 任务剧本 1.1 剧本文件概念 (1)playbook可以将多个批量操作模块功能整合,完成一件事情.(2)简化运维工作复杂度(3)playbook通过yaml语法 ...
- Redis分布式锁实战
什么是分布式锁 在单机部署的情况下,要想保证特定业务在顺序执行,通过JDK提供的synchronized关键字.Semaphore.ReentrantLock,或者我们也可以基于AQS定制化锁.单机部 ...
- Java下载文件方法
public static void download(String path, HttpServletResponse response) { try { // path是指欲下载的文件的路径. F ...
- 【Kubernetes 系列二】从虚拟机讲到 Kubernetes 架构
目录 什么是虚拟机? 什么是容器? Docker Kubernetes 架构 Kubernetes 对象 基础设施抽象 在认识 Kubernetes 之前,我们需了解下容器,在了解容器之前,我们得先知 ...
- LeetCode——264. Ugly Number II
题目: Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose prime fact ...
- abp(net core)+easyui+efcore实现仓储管理系统——使用 WEBAPI实现CURD (十三)
abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...
- 在Vue 中使用Typescript
Vue 中使用 typescript 什么是typescript typescript 为 javaScript的超集,这意味着它支持所有都JavaScript都语法.它很像JavaScript都强类 ...
- 趣味CSS3效果挑战小汇总
众所周知,在CSS3中产生了诸多优秀的特性,现在就来分享一下我这段时间对于这些特性的效果实践,希望对大家有所启发. 挑战1: 画一个对话框 要画一个对话框,首先来学习做一个三角形.其实非常的简单. & ...
- 前端小知识-js
一.对象冒充 function student(name,age){ this.name = name; this.age = age; this.show = function(){ console ...