【BZOJ4016】【FJOI2014】最短路径树问题
题意:
Description
Input
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】最短路径树问题的更多相关文章
- [BZOJ4016][FJOI2014]最短路径树问题
[BZOJ4016][FJOI2014]最短路径树问题 试题描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长 ...
- [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1796 Solved: 625[Submit][Sta ...
- 【BZOJ4016】[FJOI2014]最短路径树问题
[BZOJ4016][FJOI2014]最短路径树问题 题面 bzoj 洛谷 题解 虽然调了蛮久,但是思路还是蛮简单的2333 把最短路径树构出来,然后点分治就好啦 ps:如果树构萎了,这组数据可以卡 ...
- 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治
[BZOJ4016][FJOI2014]最短路径树问题 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径 ...
- 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)
[BZOJ4016][FJOI2014]最短路径树问题(点分治,最短路) 题面 BZOJ 洛谷 题解 首先把最短路径树给构建出来,然后直接点分治就行了. 这个东西似乎也可以长链剖分,然而没有必要. # ...
- bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 426 Solved: 147[Submit][Stat ...
- BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治
BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择 ...
- 【BZOJ-4016】最短路径树问题 Dijkstra + 点分治
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1092 Solved: 383[Submit][Sta ...
- [FJOI2014]最短路径树问题 长链剖分
[FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...
- 洛谷 [FJOI2014]最短路径树问题 解题报告
[FJOI2014]最短路径树问题 题目描述 给一个包含\(n\)个点,\(m\)条边的无向连通图.从顶点\(1\)出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多 ...
随机推荐
- 利用Java反射机制对实体类的常用操作工具类ObjectUtil
代码: ObjectUtil类: import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.Simpl ...
- Pyhton学习——Day61
class Pagination(object): def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=7): ...
- NodeJS加密算法(转)
nodejs中常用加密算法 1.Hash算法加密: 创建一个nodejs文件hash.js,输入内容如下: 1 var crypto = require('crypto'); //加载crypto ...
- Lumen5.5,使用laravel excel 下载 、导入excel文件
1.安装 首先是安装laravel excel,使用composer安装 composer require maatwebsite/excel ~2.1.0 2.配置 在bootstrap/app.p ...
- wordpress 拾遗
wordpress 拾遗 运行环境 php mySQL Apache 集成开发环境 Appserv xampp phpstudy 文章和页面的区别 文章是发布网站主要内容的地方,比如博客的文章,商城的 ...
- Layui表格编辑【不依赖Layui的动态table加载】
依赖jquer,layui/css <td class="My_edit"></td> Jquery代码 //-----[Layui表格编辑(<td ...
- [terry笔记]python三级菜单
把三级菜单输出,选择后逐层显示,”b“返回上一级菜单. menu = { '北京':{ '海淀':{ '五道口':{ 'soho':{}, '网易':{}, 'google':{} }, '中关村': ...
- Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析
相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Java并发编程(三)volatile域 Java并发编程(四)Java内存模型 Java并发编程(五)Concurr ...
- 【转载】How to Reset USB Device in Linux
USB devices are anywhere nowadays, even many embedded devices replace the traditional serial devices ...
- Vitual Router in The Cloud
VyOS and ESXi,VyOS Configuration The next step is to configure both VyOS routers. Before we do, we s ...