因为寻宝路径是一个环,所以寻宝花费的最小时间与起点无关。宝应当按照所有宝藏所在位置的 dfs 序进行才能够使得花费的时间最短。设 \(dist_i\) 表示 \(i\) 到树根的最短距离,那么树上任意两点 \(i\,,j\) 的最短距离就是 \(d_{i,j} = dist_i + dist_j - 2 \times dist_{\operatorname{lca}(i, j)}\)。这样,寻宝的环的长度就可以表示为 \(\sum_{i=1}^cd_{i,\operatorname{next}(i)}\)(\(c\) 是宝藏数量,\(\operatorname{next}(i) =
\begin{cases}
i+1,& i < c\\
1,& i = c
\end{cases}\)) 了。

添加删除宝藏都可以用 std::set 来很方便地维护。

#include <cstdio>
#include <set>
#include <algorithm> const int MAXN = 1e5 + 19; struct Edge{
int to, next, dist;
}edge[MAXN << 1]; int cnt, head[MAXN]; inline void add(int from, int to, int dist){
edge[++cnt].to = to;
edge[cnt].dist = dist;
edge[cnt].next = head[from];
head[from] = cnt;
} int dfn[MAXN], id[MAXN], t;
int dep[MAXN], fa[MAXN][20];
long long dist[MAXN], ans; void dfs(int node, int f){
dfn[node] = ++t;
dep[node] = dep[f] + 1;
id[t] = node;
fa[node][0] = f;
for(int i = 1; (1 << i) < dep[node]; ++i)
fa[node][i] = fa[fa[node][i - 1]][i - 1];
for(int i = head[node]; i; i = edge[i].next)
if(edge[i].to != f)
dist[edge[i].to] = dist[node] + edge[i].dist, dfs(edge[i].to, node);
} int lca(int x, int y){
if(dep[x] < dep[y])
std::swap(x, y);
for(int i = dep[x] - dep[y], j = 0; i; i >>= 1, ++j)
if(i & 1)
x = fa[x][j];
if(x == y)
return x;
for(int i = 18; i >= 0; --i)
if(fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
} inline long long time(int a, int b){
return dist[a] + dist[b] - 2ll * dist[lca(a, b)];
} int n, m;
bool vist[MAXN];
std::set<int>s;
std::set<int>::iterator it; int main(){
std::scanf("%d%d", &n, &m);
for(int u, v, c, i = 1; i < n; ++i)
std::scanf("%d%d%d", &u, &v, &c), add(u, v, c), add(v, u, c);
dfs(1, 0);
while(m--){
int a, b;
std::scanf("%d", &t);
if(!vist[t])
s.insert(dfn[t]);
a = id[*((it = s.lower_bound(dfn[t])) == s.begin() ? --s.end() : --it)];
b = id[*((it = s.lower_bound(dfn[t]), ++it) == s.end() ? s.begin() : it)];
if(vist[t])
s.erase(dfn[t]);
long long d = time(a, t) + time(b, t) - time(a, b);
if(vist[t])
ans -= d;
else
ans += d;
vist[t] ^= 1;
std::printf("%lld\n", ans);
}
return 0;
}

第一次接触 dfs 序和树上最小距离......要尽早把与树相关的知识点学了啊。

洛谷 P3320 [SDOI2015]寻宝游戏的更多相关文章

  1. [洛谷P3320] SDOI2015 寻宝游戏

    问题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的 ...

  2. [bzoj3991] [洛谷P3320] [SDOI2015] 寻宝游戏

    Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有 \(N\) 个村庄和 \(N-1\) 条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬 ...

  3. 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)

    被\(STL\)坑害了一个晚上,真的菜的没救了啊. 准确的说是一个叫\(reverse\ iterator\)的东西,就是我们经常用的\(rbegin()\) 有一个非常重要的性质 在反向迭代器中,+ ...

  4. P3320 [SDOI2015]寻宝游戏 解题报告

    P3320 [SDOI2015]寻宝游戏 题目描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有\(N\)个村庄和\(N-1\)条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以 ...

  5. P3320 [SDOI2015]寻宝游戏

    题目 P3320 [SDOI2015]寻宝游戏 做法 很巧妙的一种思路,懂了之后觉得大水题 首先要知道:在一棵树上标记一些点,然后从任意一点出发,遍历所有的的最小路径为\(dfs\)序从小到大遍历 那 ...

  6. Luogu P3320 [SDOI2015]寻宝游戏 / 异象石 【LCA/set】

    期末考试结束祭! 在期末考试前最后一发的测试中,异象石作为第二道题目出现QAQ.虽然知道是LCA图论,但还是敲不出来QAQ. 花了两天竞赛课的时间搞懂(逃 异象石(stone.pas/c/cpp)题目 ...

  7. luogu P3320 [SDOI2015]寻宝游戏

    大意:给定树, 要求维护一个集合, 支持增删点, 询问从集合中任取一点作为起点, 遍历完其他点后原路返回的最短长度. 集合中的点按$dfs$序排列后, 最短距离就为$dis(s_1,s_2)+...+ ...

  8. 【LG3320】[SDOI2015]寻宝游戏

    [LG3320][SDOI2015]寻宝游戏 题面 洛谷 题解 不需要建虚树的虚树2333... 贪心地想一下,起始节点肯定是在关键点上,访问顺序就是\(dfs\)序. 那么对于每次询问, \[ An ...

  9. [BZOJ3991][SDOI2015]寻宝游戏

    [BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...

随机推荐

  1. Jekyll+Github个人博客构建之路

    请参考: http://robotkang.cc/2017/03/HowToCreateBlog/

  2. MockMVC - 基于RESTful风格的Springboot,SpringMVC的测试

    MockMVC - 基于RESTful风格的SpringMVC的测试 对于前后端分离的项目而言,无法直接从前端静态代码中测试接口的正确性,因此可以通过MockMVC来模拟HTTP请求.基于RESTfu ...

  3. 模仿.NET框架ArrayList写一个自己的动态数组类MyArrayList,揭示foreach实现原理

    通过.NET反编译工具可以查看到ArrayList内部的代码,发现ArrayList并非由链表实现,而是由一个不断扩容的数组对象组成. 下面模仿ArrayList写一个自己的MyArrayList. ...

  4. kibana 开发工具介绍

    kibana上查看es集群节点信息 get /_cat/nodes?v ip heap.percent ram.percent cpu load_1m load_5m load_15m node.ro ...

  5. 树莓派Raspberry实践笔记—显示分辨率配置

    转载:http://www.cnblogs.com/atsats/p/6607886.html 如果未接显示设备,使用VNC登录后,显示分辨率很小,应该是480p,导致使用很不方便. 这里通过修改/b ...

  6. Follow somebody

    networkersdiary A personnel blog with Network Engineering articles https://networkersdiary.com/cisco ...

  7. Linux下如何查看tomcat是否启动、查看tomcat启动日志(转)

    在Linux系统下,重启Tomcat使用命令的操作! 1.首先,进入Tomcat下的bin目录 cd /usr/local/tomcat/bin 使用Tomcat关闭命令 ./shutdown.sh ...

  8. Python读取MNIST数据集

    MNIST数据集获取 MNIST数据集是入门机器学习/模式识别的最经典数据集之一.最早于1998年Yan Lecun在论文: Gradient-based learning applied to do ...

  9. idea2018.3.6,离线使用maven的方法

    (1)想办法拷贝联网电脑上已经下载好的仓库文件夹mavenRepository到离线环境的电脑上: (2)idea中按照如下图中配置: (3)打开 User settings file中设置的sett ...

  10. vs code插件大全

    一.HTML Snippets 超级使用且初级的H5代码片段以及提示 二.HTML CSS Support  让HTML标签上写class智能提示当前项目所支持的样式 三.Debugger for C ...