题意:

Description

给一个包含n个点,m条边的无向连通图。从顶点1出发,往其余所有点分别走一次并返回。
往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他点走,直到所有点都走过。
可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?
这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点A到点B的路径和点B到点A视为同一条路径。

Input

第一行输入三个正整数n,m,K,表示有n个点m条边,要求的路径需要经过K个点。接下来输入m行,每行三个正整数Ai,Bi,Ci(1<=Ai,Bi<=n,1<=Ci<=10000),表示Ai和Bi间有一条长度为Ci的边。数据保证输入的是连通的无向图。

Output

输出一行两个整数,以一个空格隔开,第一个整数表示包含K个点的路径最长为多长,第二个整数表示这样的不同的最长路径有多少条。

n<=30000,m<=60000,2<=K<=n

题解:

一眼题啊。。。SBFA写挂能怪谁QAQ

先把最小路径树建出来,然后就是点分治经典问题了;

关于最小路径树:

先以1为源点跑一边最短路,然后把对最短路没有贡献的边去掉,再按照字典序dfs一次把非树边去掉(有可能有多个最短路)即可。

代码:

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 2147483647
#define eps 1e-9
using namespace std;
typedef long long ll;
struct edge{
int v,w,next;
}a[],_a[],__a[];
struct _edge{
int u,v,w;
friend bool operator <(_edge a,_edge b){
return a.u==b.u?a.v>b.v:a.u<b.u;
}
}e[];
int n,m,k,u,v,w,ans=,anss,rt,S,tot=,_tot=,__tot=,siz[],mx[],head[],_head[],__head[],f[],g[],_f[],_g[],dis[];
bool used[],vis[];
void add(int u,int v,int w){
a[++tot].v=v;
a[tot].w=w;
a[tot].next=head[u];
head[u]=tot;
}
void _add(int u,int v,int w){
_a[++_tot].v=v;
_a[_tot].w=w;
_a[_tot].next=_head[u];
_head[u]=_tot;
}
void __add(int u,int v,int w){
__a[++__tot].v=v;
__a[__tot].w=w;
__a[__tot].next=__head[u];
__head[u]=__tot;
}
void spfa(){
queue<int>q;
bool isin[];
memset(isin,,sizeof(isin));
q.push();
isin[]=true;
dis[]=;
while(!q.empty()){
int u=q.front();
q.pop();
isin[u]=false;
for(int tmp=_head[u];tmp!=-;tmp=_a[tmp].next){
int v=_a[tmp].v;
if(dis[v]>dis[u]+_a[tmp].w){
dis[v]=dis[u]+_a[tmp].w;
if(!isin[v]){
isin[v]=true;
q.push(v);
}
}
}
}
sort(e+,e+m*+);
for(int i=;i<=m*;i++){
if(dis[e[i].v]==dis[e[i].u]+e[i].w){
__add(e[i].u,e[i].v,e[i].w);
}
}
}
void build(int u){
used[u]=true;
for(int tmp=__head[u];tmp!=-;tmp=__a[tmp].next){
int v=__a[tmp].v,w=__a[tmp].w;
if(!used[v]){
//printf("%d %d %d\n",u,v,w);
add(u,v,w);
add(v,u,w);
build(v);
}
}
}
void dfsrt(int u,int fa){
siz[u]=;
mx[u]=;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v!=fa&&!vis[v]){
dfsrt(v,u);
mx[u]=max(mx[u],siz[v]);
siz[u]+=siz[v];
}
}
mx[u]=max(mx[u],S-siz[u]);
if(mx[u]<mx[rt])rt=u;
}
void dfs(int u,int fa,int dpt,int ww){
if(dpt>k)return;
if(ww>_f[dpt]){
_f[dpt]=ww;
_g[dpt]=;
}else if(ww==_f[dpt]){
_g[dpt]++;
}
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v!=fa&&!vis[v]){
dfs(v,u,dpt+,ww+a[tmp].w);
}
}
}
void divide(int u){
f[]=,g[]=;
for(int i=;i<=k;i++)f[i]=g[i]=;
vis[u]=true;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v,w=a[tmp].w;
if(!vis[v]){
for(int i=;i<=k;i++)_f[i]=_g[i]=;
dfs(v,,,w);
for(int i=;i<=k;i++){
if(ans<f[k-i]+_f[i]){
ans=f[k-i]+_f[i];
anss=g[k-i]*_g[i];
}else if(ans==f[k-i]+_f[i]){
anss+=g[k-i]*_g[i];
}
}
for(int i=;i<=k;i++){
if(f[i]<_f[i]){
f[i]=_f[i];
g[i]=_g[i];
}else if(f[i]==_f[i]){
g[i]+=_g[i];
}
}
}
}
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(!vis[v]){
rt=,S=siz[v];
dfsrt(v,);
divide(rt);
}
}
}
int main(){
memset(dis,0x3f,sizeof(dis));
memset(head,-,sizeof(head));
memset(_head,-,sizeof(_head));
memset(__head,-,sizeof(__head));
memset(used,,sizeof(used));
memset(vis,,sizeof(vis));
scanf("%d%d%d",&n,&m,&k);
k--;
for(int i=;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
_add(u,v,w);
_add(v,u,w);
e[i*-]=(_edge){u,v,w};
e[i*]=(_edge){v,u,w};
}
spfa();
build();
mx[rt=]=,S=n;
dfsrt(,);
divide(rt);
printf("%d %d",ans,anss);
return ;
}

PS:BZOJ数据极水,我写了SPFA+没判字典序都过了

【BZOJ4016】【FJOI2014】最短路径树问题的更多相关文章

  1. [BZOJ4016][FJOI2014]最短路径树问题

    [BZOJ4016][FJOI2014]最短路径树问题 试题描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长 ...

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

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

  3. 【BZOJ4016】[FJOI2014]最短路径树问题

    [BZOJ4016][FJOI2014]最短路径树问题 题面 bzoj 洛谷 题解 虽然调了蛮久,但是思路还是蛮简单的2333 把最短路径树构出来,然后点分治就好啦 ps:如果树构萎了,这组数据可以卡 ...

  4. 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治

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

  5. 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)

    [BZOJ4016][FJOI2014]最短路径树问题(点分治,最短路) 题面 BZOJ 洛谷 题解 首先把最短路径树给构建出来,然后直接点分治就行了. 这个东西似乎也可以长链剖分,然而没有必要. # ...

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

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

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

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

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

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

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

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

  10. 洛谷 [FJOI2014]最短路径树问题 解题报告

    [FJOI2014]最短路径树问题 题目描述 给一个包含\(n\)个点,\(m\)条边的无向连通图.从顶点\(1\)出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多 ...

随机推荐

  1. C#中方向键与回车键切换控件焦点

    环境:界面上有TextBox,ComboBox等控件. 不建议把左右方向键都用来切换焦点,否则你在TextBox里面改变光标所在字符位置就不方便了. 方法一:笨方法,需为每个控件单独注册事件处理 以T ...

  2. Unity 移动键Q的三种用法 For Mac,Windows类同

    拖动整个场景:三指 (任何模式下)ALT+三指:旋转当前镜头 (任何模式下)双指前后滑动:缩放镜头 ps1:Q键移动的游戏场景,W移动的是游戏对象 ps2:三指 = 左键拖动

  3. 算法23-------岛屿的最大面积 LeetCode 695

    一.题目: 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被水包围着. 找到给定 ...

  4. 使用python备份指定目录并删除备份超过一定时长的文件

    #!/usr/bin/env python #-*- coding: utf-8 -*- """ @Project:Py @author: @Email: @Softwa ...

  5. 【【henuacm2016级暑期训练】动态规划专题 L】Civilization

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 给一个森林. 就是由很多棵树组成.. 然后会询问你其中一棵树的最长链. 初始状态的最长链可以用两遍dfs分别找最长路得到. 然后要求 ...

  6. java源码之TreeMap

    Map的单元是对键值对的处理,之前分析过的两种Map,HashMap和LinkedHashMap都是用哈希值去寻找我们想要的键值对,优点是理想情况下O(1)的查找速度. 那如果我们在一个对查找性能要求 ...

  7. 电子签章盖章之jQuery插件jquery.zsign

           简介:  使用jquery.zsign可以实现电子签章盖章效果,使用方便,只需提供自己的章图片.效果图如下:        页面引用:        <link href=&quo ...

  8. React-Native系列Android——Native与Javascript通信原理(一)

    React-Native最核心的是Native与Javascript之间的通信,并且是双向通信.Native层到Javascript层,Javascript层到Native层.虽说是两个方向,但实现上 ...

  9. windows+ubuntu双系统,在windows中访问ubuntu文件

    今天被告知ubuntu磁盘空间不足,百度得知可以通过autoremove命令清理,然而,,再也进不去ubuntu系统了,具体表现为第一次选择ubuntu之后一直是空白紫屏,如果强制关机再开机后选择ub ...

  10. ThinkPHP新建控制器

    ThinkPHP新建控制器 一.效果图 二.步骤 1.新建控制器文件 2.编写控制器文件 3.访问控制器 三.注意事项