题目传送门

题解:首先对于给定的图,需要找到那些从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 最短路径树问题 点分治 + 最短路径最小字典序的更多相关文章

  1. BZOJ 4016 最短路径树问题 最短路径树构造+点分治

    题目: BZOJ4016最短路径树问题 分析: 大家都说这是一道强行拼出来的题,属于是两种算法的模板题. 我们用dijkstra算法算出1为源点的最短路数组,然后遍历一下建出最短路树. 之后就是裸的点 ...

  2. P2993 [FJOI2014]最短路径树问题 点分治+最短路

    这道题还是非常简单的,由于我们要保证最小字典序,因此我们需要把边进行排序,然后从大到小插入,因为链式前向星是倒着存的.我们只需要先跑一个最短路,然后查询边是不是在最短路上,这个可以通过枚举边并用 di ...

  3. 【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治

    题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...

  4. bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 426  Solved: 147[Submit][Stat ...

  5. 【BZOJ-4016】最短路径树问题 Dijkstra + 点分治

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 1092  Solved: 383[Submit][Sta ...

  6. [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 1796  Solved: 625[Submit][Sta ...

  7. bzoj 4016: [FJOI2014]最短路径树问题

    bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...

  8. HDU4871 Shortest-path tree(最短路径树 + 树的点分治)

    题目大概要先求一张边有权的图的根为1的最短路径树,要满足根到各点路径序列的字典序最小:然后求这棵最短路径树包含k个结点的最长路径的长度和个数. 首先先构造出这棵字典序最小的最短路径树..好吧,我太傻逼 ...

  9. BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治

    BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择 ...

随机推荐

  1. Linux服务部署Yapi项目(安装Node Mongdb Git Nginx等)

    Linux服务部署Yapi 一,介绍与需求 1,我的安装环境:CentOS7+Node10.13.0+MongoDB4.0.10. 2,首先安装wget,用于下载node等其他工具 yum insta ...

  2. Java泛型使用的简单介绍

    目录 一. 泛型是什么 二. 使用泛型有什么好处 三. 泛型类 四. 泛型接口 五. 泛型方法 六. 限定类型变量 七. 泛型通配符 7.1 上界通配符 7.2 下界通配符 7.3 无限定通配符 八. ...

  3. zookeeper基本知识入门(一)

    之前我们在搭建hadoop分布式环境的时候用到过Zookeeper注册hadoop服务.那么到底Zookeeper在分布式环境中发挥了什么作用呢,这次我们就来讨论这个问题. 在分布式系统中通常都会有多 ...

  4. HTML/CSS:导航栏水平和垂直

    1.垂直导航栏 导航栏 = 链接列表导航栏基本上是一个链接列表,因此使用 <ul> 和 <li> 元素是非常合适的.如需构建垂直导航栏,我们只需要定义 <a> 元素 ...

  5. [转载]使用Java操作Mongodb

    HelloWorld程序 学习任何程序的第一步,都是编写HelloWorld程序,我们也不例外,看下如何通过Java编写一个HelloWorld的程序. 首先,要通过Java操作Mongodb,必须先 ...

  6. 【CodeForces - 1200A】Hotelier(水题、模拟)

    Hotelier 直接翻译了 Descriptions Amugae的酒店由10人组成10客房.房间从0开始编号0到99 从左到右. 酒店有两个入口 - 一个来自左端,另一个来自右端.当顾客通过左入口 ...

  7. Ubuntu : apt-get 命令

    apt-get 命令是 Ubuntu 系统中的包管理工具,可以用来安装.卸载包,也可以用来升级包,还可以用来把系统升级到新的版本.本文介绍 apt-get 命令的基本用法,演示环境为 Ubuntu 1 ...

  8. 带你剖析WebGis的世界奥秘----点和线的世界

    前言 昨天写了好久的博文我没保存,今天在来想继续写居然没了,气死人啊这种情况你们见到过没,所以今天重新写,我还是切换到了HTML格式的书写上.废话不多说了,我们现在就进入主题,上周我仔细研究了WebG ...

  9. MySQL-EXPLAIN执行计划Extra解释

    EXPLAIN命令输出的列中Extra字段可选值较多,这里单独说一下. 该Extra列 EXPLAIN输出包含MySQL解决查询的额外信息.以下列表说明了此列中可能出现的值.每个项目还指示JSON格式 ...

  10. java读取本机磁盘及遍历磁盘文件

    1. 获取本机所有盘符信息 //1. 获取本机盘符 File[] roots = File.listRoots(); for (int i = 0; i < roots.length; i++) ...