因为寻宝路径是一个环,所以寻宝花费的最小时间与起点无关。宝应当按照所有宝藏所在位置的 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. MySQL常用系统表大全

    MySQL5.7 默认的模式有:information_schema, 具有 61个表: m ysqL, 具有31个表: performance_schema,具有87个表; sys, 具有1个表, ...

  2. 传奇脚本:#AutoRun NPC SEC 参数说明

    传奇脚本:#AutoRun NPC SEC 参数说明 SEC:按秒运行MIN:按分运行HOUR:按小时运行DAY:按天运行RunOnDay:按每天什么时候运行RUNONWEEK:按星期几及时间运行机器 ...

  3. Nexus-vPC与FHRP

    去往vPC的流量,如何可能将会被本地的vPC成员端口所转发.FHRP的行为是被修改的,所有的FHRP路由器都会主动转发从vPC收到的流量.修改结果:如果可能,流量避免使用Peer link,这样创建一 ...

  4. leetcode 0207

    目录 ✅ 561. 数组拆分 I ✅ 1025. 除数博弈 聪明的数学归纳法: 动态规划又来了(没理解,todo 0207): ✅ 557. 反转字符串中的单词 III py 中的 字符 split ...

  5. pip源、搭建虚拟环境、git

    一.pip源 1.1 介绍 1.采用国内源,加速下载模块的速度2.常用pip源:-- 豆瓣:https://pypi.douban.com/simple-- 阿里:https://mirrors.al ...

  6. htmlunit的使用

    原文转自:https://www.cnblogs.com/davidwang456/articles/8693050.html HtmlUnit使用场景 httpClient的局限性 对于使用java ...

  7. 洛谷 T8088 RQY的舞会

    嗯... 题目链接:https://www.luogu.org/problem/T8088 这道题很好想,我想的是维护两个小根堆(当然可以用数组模拟) 然后从堆顶开始,如果两个元素的差小于1,则cnt ...

  8. 第七届蓝桥杯javaB组真题解析-抽签(第五题)

    题目 /* 抽签 X星球要派出一个5人组成的观察团前往W星. 其中: A国最多可以派出4人. B国最多可以派出2人. C国最多可以派出2人. .... 那么最终派往W星的观察团会有多少种国别的不同组合 ...

  9. Python 基础之面向对象之装饰器@property

    一.定义 装饰器@property可以把方法变成属性使用作用: 控制类内成员的获取 设置 删除获取 @property设置 @自定义名.setter删除 @自定义名.deleter 二.具体实现 1. ...

  10. Kali 2020.1 默认密码不是toor

    官方2020年一月28日的文章中指出root/toor is dead. Long live kali/kali. 登录用户名和密码是kali:kali 但是虚拟机镜像下载页面没有及时更新,仍然提示登 ...