题意:

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. 利用Java反射机制对实体类的常用操作工具类ObjectUtil

    代码: ObjectUtil类: import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.Simpl ...

  2. Pyhton学习——Day61

    class Pagination(object): def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=7): ...

  3. NodeJS加密算法(转)

    nodejs中常用加密算法   1.Hash算法加密: 创建一个nodejs文件hash.js,输入内容如下: 1 var crypto = require('crypto'); //加载crypto ...

  4. Lumen5.5,使用laravel excel 下载 、导入excel文件

    1.安装 首先是安装laravel excel,使用composer安装 composer require maatwebsite/excel ~2.1.0 2.配置 在bootstrap/app.p ...

  5. wordpress 拾遗

    wordpress 拾遗 运行环境 php mySQL Apache 集成开发环境 Appserv xampp phpstudy 文章和页面的区别 文章是发布网站主要内容的地方,比如博客的文章,商城的 ...

  6. Layui表格编辑【不依赖Layui的动态table加载】

    依赖jquer,layui/css <td class="My_edit"></td> Jquery代码 //-----[Layui表格编辑(<td ...

  7. [terry笔记]python三级菜单

    把三级菜单输出,选择后逐层显示,”b“返回上一级菜单. menu = { '北京':{ '海淀':{ '五道口':{ 'soho':{}, '网易':{}, 'google':{} }, '中关村': ...

  8. Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析

    相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Java并发编程(三)volatile域 Java并发编程(四)Java内存模型 Java并发编程(五)Concurr ...

  9. 【转载】How to Reset USB Device in Linux

    USB devices are anywhere nowadays, even many embedded devices replace the traditional serial devices ...

  10. Vitual Router in The Cloud

    VyOS and ESXi,VyOS Configuration The next step is to configure both VyOS routers. Before we do, we s ...