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个点的路径最长为多长,第二个整数表示这样的不同的最长路径有多少条。
 

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

首先求字典序最小的最短路树,考虑将边拆成两条单向边,然后按终点从大到小排序,按序插入链式前向星中,保证找到的第一条最短路就是字典序最小的。

点分就比较裸了,记深度为 $i$ 时最大的路径长度为 $sum_i$ ,长度为 $sum_i$ ,且深度为 $i$ 的路径数为 $cnt_i$ 直接转移就好了。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct ZYYS
{
int u,v,d;
}E[];
struct Node
{
int next,to,d;
}edge[];
int num,head[],dist[],pre[],pred[];
int size[],maxsize[],minsize,root,w[],k,ans,dep_max,n,m,cnt,c[];
bool vis[];
bool cmp(ZYYS a,ZYYS b)
{
if (a.u==b.u) return a.v>b.v;
return a.u<b.u;
}
void add(int u,int v,int d)
{
num++;
edge[num].next=head[u];
head[u]=num;
edge[num].to=v;
edge[num].d=d;
}
void SPFA()
{int i;
queue<int>Q;
memset(dist,/,sizeof(dist));
Q.push();
dist[]=;
while (Q.empty()==)
{
int u=Q.front();
Q.pop();
vis[u]=;
for (i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if (dist[v]>dist[u]+edge[i].d)
{
pre[v]=u;
pred[v]=edge[i].d;
dist[v]=dist[u]+edge[i].d;
if (vis[v]==)
{
vis[v]=;
Q.push(v);
}
}
}
}
}
void get_size(int x,int pa)
{int i;
size[x]=;
maxsize[x]=;
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (v==pa||vis[v]) continue;
get_size(v,x);
size[x]+=size[v];
maxsize[x]=max(maxsize[x],size[v]);
}
}
void get_root(int x,int pa,int r)
{int i;
maxsize[x]=max(size[r]-size[x],maxsize[x]);
if (maxsize[x]<minsize)
{
minsize=maxsize[x];
root=x;
}
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (v==pa||vis[v]) continue;
get_root(v,x,r);
}
}
void get_ans(int x,int pa,int dis,int dep)
{int i;
if (c[k--dep]&&w[k--dep]+dis==ans)
cnt+=c[k--dep];
else if (c[k--dep]&&ans<w[k--dep]+dis)
ans=w[k--dep]+dis,cnt=c[k--dep];
dep_max=max(dep_max,dep);
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (v==pa||vis[v]||dep==k-) continue;
get_ans(v,x,dis+edge[i].d,dep+);
}
}
void get_update(int x,int pa,int dis,int dep)
{int i;
if (dis>w[dep]) w[dep]=dis,c[dep]=;
else if (dis==w[dep]) c[dep]++;
dep_max=max(dep_max,dep);
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (v==pa||vis[v]||dep==k-) continue;
get_update(v,x,dis+edge[i].d,dep+);
}
}
void slove(int x)
{int i;
minsize=2e9;
get_size(x,);
get_root(x,,x);
vis[root]=;
dep_max=;
c[]=;
for (i=head[root];i;i=edge[i].next)
{
int v=edge[i].to;
if (vis[v]) continue;
get_ans(v,root,edge[i].d,);
get_update(v,root,edge[i].d,);
}
for (i=;i<=dep_max;i++)
w[i]=,c[i];
for (i=head[root];i;i=edge[i].next)
{
int v=edge[i].to;
if (vis[v]==)
slove(v);
}
}
int main()
{int i,u,v,d;
cin>>n>>m>>k;
for (i=;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&d);
E[*i-].u=u,E[*i-].v=v,E[*i-].d=d;
E[*i].u=v;E[*i].v=u,E[*i].d=d;
}
sort(E+,E+*m+,cmp);
for (i=;i<=*m;i++)
{
add(E[i].u,E[i].v,E[i].d);
}
SPFA();
memset(head,,sizeof(head));
num=;
for (i=;i<=n;i++)
add(i,pre[i],pred[i]),add(pre[i],i,pred[i]);
slove();
cout<<ans<<' '<<cnt<<endl;
}

[FJOI2014]最短路径树问题的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. JavaScript(第二十三天)【事件入门】

    JavaScript事件是由访问Web页面的用户引起的一系列操作,例如:用户点击.当用户执行某些操作的时候,再去执行一系列代码.   一.事件介绍 事件一般是用于浏览器和用户操作进行交互.最早是IE和 ...

  2. Beta 第一天

    一.今日任务 重新熟悉整体项目 对整个项目在未来的beta冲刺中进程有一个合理的规划 由于我们送出的是一个负责前端的成员,引入的也是一个负责前端工作的女生,(女生做起美工比起男生更加得心应手吧)所以我 ...

  3. JAVA反射机制基础概念

    反射机制:所谓的反射机制就是java语言在运行时拥有一项自观的能力.通过这种能力可以彻底的了解自身的情况为下一步的动作做准备.下面具体介绍一下java的反射机制.这里你将颠覆原来对java的理解. J ...

  4. Java Client/Server 基础知识

    Java的网络类库支持多种Internet协议,包括Telnet, FTP 和HTTP (WWW),与此相对应的Java网络类库的子类库为: Java.net  Java.net.ftp  Java. ...

  5. Python多线程案例

    from time import ctime,sleep import threading def music(): for i in range(2): print ("I was lis ...

  6. Flask 页面缓存逻辑,jinja2 过滤器,测试器

    回调接入点-页面缓存逻辑 from flask import Flask,request,render_template from werkzeug.contrib.cache import Simp ...

  7. [Cerc2013]Magical GCD

    https://vjudge.net/problem/UVA-1642 题意:在一个序列中,找出一段连续的序列,使得长度*gcd最大 固定右端点,当左端点从左向右移动时,gcd不变或变大 gcd相同时 ...

  8. 5种做法实现table表格中的斜线表头效果

    table表格,这个东西大家肯定都不陌生,代码中我们时常都能碰到,那么给table加一个斜线的表头有时是很有必要的,但是到底该怎么实现这种效果呢? 我总结了以下几种方法: 1.最最最简单的做法 直接去 ...

  9. Scala 操作符与提取器

    实际上Scala没有操作符, 只是以操作符的格式使用方法. 操作符的优先级取决于第一个字符(除了赋值操作符), 而结合性取决于最后一个字符 Scala的操作符命名更加灵活:) 操作符 中置操作符(In ...

  10. 《网络》:设置三个密码:通过console口连接设备,进入特权模式,登录Telnet

    软件:Cisco Packet Tracer Instructor 软件下载链接在上一篇文章中. 内容:通过设置三个密码,熟悉采用Telnet方式配置交换机的方法. 细节说明:计算机的IP地址和交换机 ...