思路:最短路+点分治

提交:2次

错因:更新桶的时候没有重置,而直接加上了。

题解:

对于构建最短路树,我们可以先跑最短路,然后dfs一遍连边。

然后就是点分治了,还是一些桶,存点数为\(x\)的最长路径的条数。记得更新路径长度时桶要清零。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#define R register int
using namespace std;
namespace Luitaryi {
template<class I> inline I g(I& x) { x=0; register I f=1;
register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
} const int N=30010,M=60010,Inf=0x3f3f3f3f;
int n,m,K,rt,tot,cnt,size,sum,ans=-1,C; bool vis[N];
int vr[N<<1],nxt[N<<1],fir[N],w[N<<1],sz[N],d[N],c[N],mx[N];
int dis[N],buf[N],mem[N],q[N],q2[N];
vector<pair<int,int> > e[N];
inline void add(int u,int v,int ww) {
vr[++cnt]=v,nxt[cnt]=fir[u],w[cnt]=ww,fir[u]=cnt;
vr[++cnt]=u,nxt[cnt]=fir[v],w[cnt]=ww,fir[v]=cnt;
}
inline void spfa() { memset(d,0x3f,sizeof(d));
queue<int>q; q.push(1),d[1]=0,vis[1]=true;
while(q.size()) { R u=q.front(); q.pop(),vis[u]=false;
for(R i=0,lim=e[u].size();i<lim;++i) { R v=e[u][i].first,w=e[u][i].second;
if(d[v]>d[u]+w) {
d[v]=d[u]+w; if(!vis[v]) vis[v]=true,q.push(v);
}
}
}
}
inline void dfs(int u) { vis[u]=true;
sort(e[u].begin(),e[u].end());
for(R i=0,lim=e[u].size();i<lim;++i) { R v=e[u][i].first,w=e[u][i].second;
if(vis[v]||d[v]!=d[u]+w) continue;
add(u,v,w); dfs(v);
}
}
inline void getsz(int u,int fa) {
sz[u]=1,mx[u]=0;
for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(v==fa||vis[v]) continue;
getsz(v,u),sz[u]+=sz[v];
mx[u]=max(mx[u],sz[v]);
} mx[u]=max(mx[u],sum-sz[u]);
if(mx[u]<mx[rt]) rt=u;
}
inline void getdis(int u,int fa) {
q[++tot]=c[u],q2[tot]=d[u];
for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(v==fa||vis[v]) continue;
c[v]=c[u]+1,d[v]=d[u]+w[i];
if(c[v]<=K) getdis(v,u);
}
}
inline void solve(int u,int fa) { vis[u]=true;
buf[++size]=1,mem[1]=1,dis[1]=0;
for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(v==fa||vis[v]) continue;
d[v]=w[i],c[v]=1,getdis(v,u);
for(R i=1;i<=tot;++i) {
if(mem[K-q[i]]) {
if(ans<q2[i]+dis[K-q[i]]) ans=q2[i]+dis[K-q[i]],C=mem[K-q[i]];
else if(ans==q2[i]+dis[K-q[i]]) C+=mem[K-q[i]];
}
}
for(R i=1;i<=tot;++i)
if(mem[q[i]+1]) {
if(dis[q[i]+1]==q2[i]) ++mem[q[i]+1];
else if(dis[q[i]+1]<q2[i]) mem[q[i]+1]=1,dis[q[i]+1]=q2[i];
}
else buf[++size]=q[i]+1,++mem[q[i]+1],dis[q[i]+1]=q2[i]; tot=0;
} while(size) mem[buf[size]]=0,dis[buf[size]]=0,--size;
for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(v==fa||vis[v]) continue;
sum=sz[v]; rt=0,mx[0]=n; getsz(v,u),getsz(rt,0),solve(rt,u);
}
}
inline void main() { freopen("in.in","r",stdin);
g(n),g(m),g(K); for(R i=1,u,v,w;i<=m;++i)
g(u),g(v),g(w),e[u].push_back(make_pair(v,w)),
e[v].push_back(make_pair(u,w));
spfa(),dfs(1); memset(vis,0,sizeof(vis));
sum=n,mx[0]=Inf; getsz(1,-1),getsz(rt,-1);
solve(rt,-1),printf("%d %d\n",ans,C);
}
} signed main() {Luitaryi::main(); return 0;}

2019.08.31

69

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

  1. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)

    题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...

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

    这道题还是非常简单的,由于我们要保证最小字典序,因此我们需要把边进行排序,然后从大到小插入,因为链式前向星是倒着存的.我们只需要先跑一个最短路,然后查询边是不是在最短路上,这个可以通过枚举边并用 di ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Python--时间模块time模块

    原地址:https://finthon.com/python-time/ Python时间模块——time模块 简介 在数据处理当中,经常会碰到处理时间的问题.比如:在序列预测的过程中,需要通过学习一 ...

  2. Scrapy各部分运行机制?Xpath为None?多层Response如何编写?搞定Scrapy的坑

    前言 Scrapy那么多模块都是怎么结合的啊?明明在chrome上的xpath helper插件写好了xpath,为什么到程序就读取的是None?Scrapy可以直接写多层response么?难道必须 ...

  3. 跳转语句 break;continue; return; goto 区别用法

    C语言是按顺序执行语句的语言——一个接一个.即使它有条件语句或循环语句,程序的流程也是自上而下的.没有顺序流的随机跳转或跳转.但我们的程序是为了满足任何现实世界的需求,一个接一个地执行永远不会很直接. ...

  4. System函数的使用说明

    #inlcude<stdlib.h> int system(const char* command) 功能:在已经运行的程序中调用另一个外部程序 参数:外部可执行程序的名字 返回值:不同系 ...

  5. SAS学习笔记42 宏程序

    Autocall Macro是由SAS提供的一些实现特定功能的Macro Program,可以在代码中直接使用 其中以Q开头的相比正常的多了隐藏特殊字符的功能(称之为Macro Quoting): K ...

  6. springboot 集成fastDfs

    pom.xml 引入依赖 <dependency> <groupId>com.github.tobato</groupId> <artifactId>f ...

  7. BZOJ4199 NOI2015品酒大会(后缀树)

    利用SAM建出后缀树,树上每个节点计算一下|right|.right集合中ai的最大.次大.最小.次小值即可. #include<iostream> #include<cstdio& ...

  8. ASP.NET Core 入门(1)(搭建环境CentOS)

    一.CentOS 7 安装 下载CentOS http://isoredirect.centos.org/centos/7/isos/x86_64/  选择其中下载即可. 下载完成后打开vmware准 ...

  9. 括号配对检测 A

    括号配对检测 A ‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮ ...

  10. vue 实现的评分小星星组件,包括半星

    github源码地址:https://github.com/13476075014/node-vue/blob/master/mynodeproject/13.sell/sell/src/compon ...