【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\)出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多 ...
随机推荐
- Win7下安装Flash低版本
我把HKEY_LOCAL_MACHINE\SOFTWARE\Macromedia\FlashPlayer\SafeVersions中高于要装的版本的项目都删了,还是不行. 看了这个帖子后发现,原来64 ...
- Maven private reprository 更新
maven对构件的更新判断基本上是两种,一种是稳定版本,一种是maven特有的SNAPSHOT版本. 稳定版本很好判断,直接根据maven构件的坐标体系就能够获得.先从本地仓库中找,如果本地仓库没有, ...
- HDU 2095 find your present (2)( 位运算 )
链接:传送门 题意:给出n个数,这n个数中只有一种数出现奇数次,其他全部出现偶数次,让你找到奇数次这个数 思路:简单异或运算题 /*********************************** ...
- UVALive-8072 Keeping On Track 树形dp 联通块之间缺失边的个数
题目链接:https://cn.vjudge.net/problem/UVALive-8072 题意 给出n+1个点和n条边,每对点之间只能存在一条边. 现在要找出一个节点,使得去掉这个点后,所剩每对 ...
- hadoop 使用java操作hdfs
1.创建目录 import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.ha ...
- class的基本操作方法
JavaScript语言中,生成实例对象的传统方法是通过构造函数 function Point(x,y){ this.x = x; this.y = y; } Point.prototype.toSt ...
- 【codeforces 508D】The Maths lecture
[题目链接]:http://codeforces.com/problemset/problem/507/D [题意] 让你找符合这样数字的数的个数: 1.有n个数码 2.某个后缀%k的值为0 3.大于 ...
- Git学习总结(9)——如何构建你自己的 Git 服务器
现在我们将开始学习如何构建一个Git服务器,如何在具体的事件中写一个针对特定的触发操作的自定义Git(例如通告),如何发布你的代码到一个网站. 目前为止,用户对Git的焦点主要在Git的使用上.这篇文 ...
- [ReactVR] Start a Virtual Reality Project Using the React VR CLI
We will learn how to set up a React VR project, run the development mode with hot reloading, and tak ...
- 图片3d轮放查看效果
本功能比較简单,就是一个大幕.左右滚动播放图片. 关键点在于怎样实现平滑的滚动,包含动画效果,3d效果等. <style> img { position: absolute; top:20 ...