博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ】3991: [SDOI2015]寻宝游戏 虚树+DFS序+set
阅读量:7026 次
发布时间:2019-06-28

本文共 1343 字,大约阅读时间需要 4 分钟。

【题意】给定n个点的带边权树,对于树上存在的若干特殊点,要求任选一个点开始将所有特殊点走遍后返回。现在初始没有特殊点,m次操作每次增加或减少一个特殊点,求每次操作后的总代价。n,m<=10^5。

【算法】虚树+DFS序+set

【题解】每次询问相当于求两倍虚树路径和

模拟虚树上dfs序的转移会发现,dfs序相邻(1和n视为相邻)的两点路径值的总和,就是虚树路径和的两倍

那么只需要用set维护特殊点集合,每次根据前驱后继更改答案。

#include
#include
#include
#include
#define ll long longusing namespace std;const int maxn=100010;int n,m,first[maxn],tot,deep[maxn],in[maxn],dfsnum=0,f[maxn][30];ll dis[maxn];bool v[maxn];struct cmp{ bool operator ()(int x,int y){
return in[x]
s;set
::iterator it;struct edge{ int v,w,from;}e[maxn*2];void insert(int u,int v,int w){tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}void dfs(int x,int fa){ in[x]=++dfsnum; for(int j=1;(1<
<=deep[x];j++)f[x][j]=f[f[x][j-1]][j-1]; for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){ deep[e[i].v]=deep[x]+1; dis[e[i].v]=dis[x]+e[i].w; f[e[i].v][0]=x; dfs(e[i].v,x); }}int lca(int x,int y){ if(deep[x]
=0;i--)if((1<
<=deep[x]&&f[x][i]!=f[y][i]){ x=f[x][i];y=f[y][i]; } return f[x][0];}ll p(int x,int y){ return dis[x]+dis[y]-2*dis[lca(x,y)];}int main(){ scanf("%d%d",&n,&m); for(int i=1;i
1)sum+=p(a,b)-p(a,x)-p(b,x); s.erase(x);v[x]=0; } printf("%lld\n",sum); } return 0;}
View Code

 

转载于:https://www.cnblogs.com/onioncyc/p/8470844.html

你可能感兴趣的文章
AutoOps 1.8 版本
查看>>
烂泥:centos安装LVM方式
查看>>
写时拷贝(方案一)
查看>>
教程Micropython自制小型家庭气象站(萝卜教育)
查看>>
Redis源码分析系列26:对redis的一点小感触
查看>>
phpstudy 性能调优
查看>>
JDK源码解读(1)ArrayList和LinkedList
查看>>
第22讲: Scala中的闭包实战详解
查看>>
linux信号解释(1)
查看>>
串口DTU设备常见问题处理
查看>>
28.umask值
查看>>
文件操作工具类
查看>>
nginx教程从入门到精通(ttlsa出品)
查看>>
squid日志之access.log格式+内容
查看>>
我们是如何上网?
查看>>
我的友情链接
查看>>
梯度下降法的三种形式BGD、SGD以及MBGD
查看>>
Win10中文语言包安装方法
查看>>
Java之路--Javase篇 泛型
查看>>
SecureCRT自动记录日志
查看>>