BZOJ 4016 最短路径树问题 最短路径树构造+点分治
2024-10-20 11:26:39
题目:
分析:
大家都说这是一道强行拼出来的题,属于是两种算法的模板题。
我们用dijkstra算法算出1为源点的最短路数组,然后遍历一下建出最短路树。
之后就是裸的点分治算法,一个桶,两个变量就解决了这道题。
代码:
#include<bits/stdc++.h>
#define pi pair<int,int>
#define pq priority_queue
#define mp(a,b) make_pair(a,b)
#define ms(a,x) memset(a,x,sizeof(a))
using namespace std;
const int N=;
vector< pi >g[N];
struct node{int y,z,nxt;}e[N*];
int n,m,k,h[N],c=,dis[N],vis[N],nm[N];
int ans2,md,rt,sm,siz[N],s[N],ans,f[N];
pq< pi,vector< pi >,greater< pi > >q;
void add(int x,int y,int z){
e[++c]=(node){y,z,h[x]};h[x]=c;
e[++c]=(node){x,z,h[y]};h[y]=c;
} void dij(){
ms(vis,);ms(dis,0x3f);
dis[]=;q.push(mp(,));
while(!q.empty()){
int x=q.top().second;q.pop();
if(vis[x]) continue;vis[x]=;
for(int i=;i<g[x].size();i++){
int y=g[x][i].first,
d=g[x][i].second;
if(dis[y]>dis[x]+d) dis[y]=dis[x]+d,
q.push(mp(dis[y],y));
}
} return ;
} void rebuild(int x){
vis[x]=;
for(int i=;i<g[x].size();i++){
int y=g[x][i].first,d=g[x][i].second;
if(vis[y]||dis[x]+d!=dis[y]) continue;
add(x,y,d);rebuild(y);
} return ;
} void getrt(int x,int fa){
siz[x]=;f[x]=;
for(int i=h[x],y;i;i=e[i].nxt)
if(!vis[y=e[i].y]&&y!=fa) getrt(y,x),
siz[x]+=siz[y],f[x]=max(f[x],siz[y]);
f[x]=max(f[x],sm-siz[x]);
if(f[rt]>f[x]) rt=x;return ;
} void dfs(int x,int fa,int nw){
md=max(md,nw);
if(nw==k-){
if(ans==dis[x]) ans2++;
if(dis[x]>ans) ans2=,
ans=dis[x];return ;
} int nans=-;
if(s[k--nw]!=-) nans=dis[x]+s[k--nw];
if(ans==nans) ans2+=nm[k--nw];
if(nans>ans) ans2=nm[k--nw],ans=nans;
for(int i=h[x],y;i;i=e[i].nxt)
if(!vis[y=e[i].y]&&y!=fa)
dis[y]=dis[x]+e[i].z,dfs(y,x,nw+);
} void update(int x,int fa,int nw){
if(nw==k-) return ;
if(s[nw]==dis[x]) nm[nw]++;
else s[nw]=max(s[nw],dis[x]),nm[nw]=;
for(int i=h[x],y;i;i=e[i].nxt)
if(!vis[y=e[i].y]&&y!=fa) update(y,x,nw+);
} void solve(int x){
md=;vis[x]=;
for(int i=h[x],y;i;i=e[i].nxt)
if(!vis[y=e[i].y]) dis[y]=e[i].z,
dfs(y,x,),update(y,x,);
for(int i=;i<=md;i++) s[i]=-,nm[i]=;
for(int i=h[x],y;i;i=e[i].nxt)
if(!vis[y=e[i].y]) sm=siz[y],rt=,
getrt(y,x),solve(rt);
} int main(){
f[]=0x3f3f3f3f;scanf("%d%d%d",&n,&m,&k);
for(int i=,x,y,z;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
g[x].push_back(mp(y,z));
g[y].push_back(mp(x,z));
} for(int i=;i<=n;i++)
sort(g[i].begin(),g[i].end());
dij();ms(vis,);rebuild();
sm=n;rt=;ms(vis,);
ms(dis,);ms(s,-);
getrt(,);solve(rt);
printf("%d %d\n",ans,ans2);
return ;
}
最短路树+点分治
最新文章
- AngularJS过滤器filter-时间日期格式-渲染日期格式-$filter
- jQuery:实现两个<;select>;控件的互移操作
- 【JAVA】Runtime
- 01 Hibernate错题分析
- MusigCV安装
- 怎么保护PDF文档和扫描文件里的机密信息
- sqool导出oracle数据
- 【英文】Bingo口语笔记(18) - Cover系列
- Loadrunner 运行场景时:missing newline in XXX.dat 错误解决
- jQuery Validation让验证变得如此容易(二)
- 选择LDO的方法(转)
- eclipse如何把多个项目用不同的文件夹分隔开
- File API简介
- Material04 MdListModule模块
- 对使用多个swiper下标有时显示不出来的问题
- ABP官方文档翻译 10.1 ABP Nuget包
- Error[Pe020]: identifier ";FILE"; is undefined
- 第一章:HTML5的基础
- 【mybatis源码学习】mybtias扩展点
- RNN(Recurrent Neural Networks)公式推导和实现
热门文章
- ko.js循环绑定值问题(工作遇见)
- Codeforces Round #542(Div. 2) B.Two Cakes
- 洛谷P2514||bzoj2426 [HAOI2010]工厂选址
- VMware每次联网都需要还原默认设置解决办法
- Hive_Hive的管理_web界面方式
- 自己开发shell脚本实现一键化安装。
- python 多继承(新式类) 二
- 牛客网Java刷题知识点之多线程同步的实现方法有哪些
- yield和yield from
- CF1061B Views Matter