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

Time Limit: 5 Sec  Memory Limit: 512 MB
Submit: 1796  Solved: 625
[Submit][Status][Discuss]

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&
lt;=10000),表示Ai和Bi间有一条长度为Ci的边。数据保证输入的是连通的无向图。
 
 

Output

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

Sample Input

6 6 4
1 2 1
2 3 1
3 4 1
2 5 1
3 6 1
5 6 1

Sample Output

3 4

HINT

对于所有数据n<=30000,m<=60000,2<=K<=n。
数据保证最短路径树上至少存在一条长度为K的路径。
2016.12.7新加数据一组by - wyx-150137

Source

这题的题目已经告诉我们该怎么做了,先用dijkstra(或者spfa)找出最短路径图存在vector里,然后以字典序的优先原则dfs建出最短路径树,最后在树上点分治就好了。

写的时候头是晕的,加上数组很多,错误百出。

代码用时:2h

 #include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=,inf=;
int n,m,K,u,v,w,rt,sm,sum,mx,ans,num,vi[N],vv[N],dep[N],vis[N],d[N],s[N],sz[N],dis[N],sf[N],sg[N],f[N],g[N];
struct P{ int x,v; };
bool operator<(P a,P b){ return a.v>b.v; }
priority_queue<P>Q;
vector<int>V[N]; struct E{
int cnt,nxt[N<<],to[N<<],val[N<<],h[N];
void add(int u,int v,int w){ nxt[++cnt]=h[u]; to[cnt]=v; val[cnt]=w; h[u]=cnt; }
void dijkstra(){
rep(i,,n) d[i]=inf; d[]=; Q.push((P){,});
while (!Q.empty()){
int x=Q.top().x; Q.pop();
if (vi[x]) continue; vi[x]=;
For(i,x) if (d[k=to[i]]+val[i]==d[x]) V[k].push_back(i^);
For(i,x) if (d[k=to[i]]>d[x]+val[i]) d[k]=d[x]+val[i],Q.push((P){k,d[k]});
}
} void getroot(int x,int fa){
sz[x]=; s[x]=;
For(i,x) if (!vis[k=to[i]] && k!=fa) getroot(k,x),sz[x]+=sz[k],s[x]=max(s[x],sz[k]);
s[x]=max(s[x],sum-sz[x]);
if (s[x]<s[rt]) rt=x;
} void getdeep(int x,int fa){
For(i,x) if (!vis[k=to[i]] && k!=fa){
dep[k]=dep[x]+; dis[k]=dis[x]+val[i]; mx=max(mx,dep[k]);
if (dis[k]>f[dep[k]]) f[dep[k]]=dis[k],sf[dep[k]]=;
else if (dis[k]==f[dep[k]]) sf[dep[k]]++;
getdeep(k,x);
}
} void que(int x){
vis[x]=; int sm=;
For(i,x) if (!vis[k=to[i]]){
mx=dep[k]=; dis[k]=f[]=val[i]; sf[]=; getdeep(to[i],x);
rep(j,,min(mx,K)){
if (ans<f[j]+g[K-j]) ans=f[j]+g[K-j],num=sf[j]*sg[K-j];
else if (ans==f[j]+g[K-j]) num+=sf[j]*sg[K-j];
}
rep(j,,min(mx,K)){
if (g[j]<f[j]) g[j]=f[j],sg[j]=sf[j];
else if (g[j]==f[j]) sg[j]+=sf[j];
}
rep(j,,mx) f[j]=-inf,sf[j]=;
sm=max(sm,mx);
}
rep(i,,min(sm,K)) g[i]=-inf,sg[i]=;
For(i,x) if (!vis[k=to[i]]) rt=,sum=sz[k],getroot(k,x),que(rt);
}
}G,G1;
bool cmp(int a,int b){ return G.to[a]<G.to[b]; } void dfs(int x){
sort(V[x].begin(),V[x].end(),cmp);
rep(i,,(int)V[x].size()-) if (!vv[G.to[V[x][i]]])
vv[G.to[V[x][i]]]=,G1.add(x,G.to[V[x][i]],G.val[V[x][i]]),G1.add(G.to[V[x][i]],x,G.val[V[x][i]]),dfs(G.to[V[x][i]]);
} int main(){
freopen("bzoj4016.in","r",stdin);
freopen("bzoj4016.out","w",stdout);
scanf("%d%d%d",&n,&m,&K); G.cnt=G1.cnt=; K--;
rep(i,,m) scanf("%d%d%d",&u,&v,&w),G.add(u,v,w),G.add(v,u,w);
G.dijkstra(); vv[]= ; dfs();
g[]=; sg[]=; s[]=inf; sum=n; G1.getroot(,); G1.que(rt);
printf("%d %d\n",ans,num);
return ;
}

[BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)的更多相关文章

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

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

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

    挺简单的,但是给人一种把两个问题强行弄到一起的感觉. 十分不好写. Code: #include <queue> #include <cstdio> #include < ...

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

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

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

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

  5. BZOJ 4016 [FJOI2014]最短路径树问题 (贪心+点分治)

    题目大意:略 传送门 硬是把两个题拼到了一起= = $dijkstra$搜出单源最短路,然后$dfs$建树,如果$dis_{v}=dis_{u}+e.val$,说明这条边在最短路图内,然后像$NOIP ...

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

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

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

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

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

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

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

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

随机推荐

  1. 20155335俞昆《Java程序设计》第五周总结

    #  20155335    <Java程序设计>第五周学习总结 ##  教材学习内容总结 ##  教材学习中的问题和解决过程 对于异常处理,程序中总有意想不到的状况所引发的的错误,Jav ...

  2. VS 2010 应用程序无法启动

    其实一般遇到这种问题, 不管是debug还是release, 也不用看提示的内存地址, 首先应该想到库是否包含正确. 一个可能的错误就是32位或64位不匹配的错误. 比如环境变量设的是64位的Open ...

  3. RMQ之ST求区间最大值

    题目链接:https://cn.vjudge.net/problem/HRBUST-1188 每一次按照二进制的方式进行更新,二维数组dp [i] [j],i表示下标,j表示从i 开始的往后移动2的j ...

  4. 72.xilinx vivado zynq vdma仿真及应用详解(一)

    很多人用zynq平台做视频图像开发,但是对vdma了解比较少,上手起来稍微有些困难,我针对这一现象,做了一个基于vivado和modelsim的仿真和应用测试工程,并写篇文章做些介绍,希望能对大家有帮 ...

  5. URAL题解三

    URAL题解三 URAL 1045 题目描述:有\(n\)个机场,\(n-1\)条航线,任意两个机场有且只有一种方案联通.现有两个恐怖分子从\(m\)号机场出发,第一个人在机场安装炸弹,乘坐飞机,引爆 ...

  6. caffe Python API 之Solver定义

    from caffe.proto import caffe_pb2 s = caffe_pb2.SolverParameter() path='/home/xxx/data/' solver_file ...

  7. VI编辑,配置文件

    1,VI编辑 vi 分为3种模式 1>一般模式: [Ctrl + f  ]         下一页 [Ctrl + b ]         上一页 [n+ enter]  向下移动n行 eg:2 ...

  8. groovy的三个强劲属性(一)Gpath

            我们先从GPath开始,一个GPath是groovy代码的一个强劲对象导航的结构,名称的选择与XPath相似,XPath是一个用来描述XML(和等价物)文档的标准,正如XPath,GP ...

  9. UBuntu14.04 --vim安装YouCompleteMe插件

    说明 我电脑的系统参数(用 uname -a命令查看)如下: Linux avyn-Lenovo --generic #-Ubuntu SMP Tue Mar :: UTC i686 i686 i68 ...

  10. Nginx 原理篇

    前言 在学习 Nginx 之前,我们首先有必要搞清楚下面几个问题: 1. Web服务器是怎么工作的? 2. Apache 与 Nginx 有何异同? 3. Nginx 工作模式是怎样的? 下面就围绕这 ...