题目大意

给你\(k\)个点,让这一些点和一号节点断开,删去某一些边,求最小的删去边权之和。

做题的心路历程

做了\(HG\)昨天的模拟赛,深深感觉到了窝的菜,所以为了\(A\)掉T1这一道毒瘤,窝就来学习一下虚树。
学到一半,感觉虚树的原理还是比较简单的,就是把需要求的点建一棵和原来的树长得十分相似的一棵树,然后在这个树上做\(DP\)。
但是,我写到完了,就一直T。也不知道为什么。
然后删掉了所有的memset就瞬间跑了出来。原来是因为自己太怂了。。。

题解

首先如果考虑最简单的树形\(DP\)。
\(f[i]\)表示以\(i\)为根节点的答案。
那么我们需要预处理出每一个节点到根节点\(1\)的最小边权设为\(me[i]\),那么就得到了\(f[i]=\sum \ min(f[i],me[i])\)
但是发现,如果每一个询问都做一遍树形\(DP\),那么一定是要炸的。
那么就对于我们需要询问的节点建立一个树,然后在这个树上跑DP。

代码

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#define N 550005
#define ms(a, b) memset(a, b, sizeof(a))
#define ll long long
#define BIT 19
using namespace std;
template <typename T> void read(T &x) {x = 0; T fl = 1; char ch = 0;for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') fl = -1;for (; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);x *= fl;
}
struct edge { int to, nt, w; } E[N << 1];
vector<int> G[N];
int H[N], dfn[N], ispoint[N], f[N][BIT + 5], dep[N], p[N], stk[N];
ll me[N];
int cnt, __dfn, n, Q, k, top;
void add_edge(int u, int v, int w) { E[++ cnt] = (edge){v, H[u], w}; H[u] = cnt; }
bool cmp(int A, int B) { return dfn[A] < dfn[B]; }
void dfs1(int u, int fa) {f[u][0] = fa; dfn[u] = ++ __dfn; dep[u] = dep[fa] + 1;  for (int i = 1; i <= BIT; i ++) f[u][i] = f[f[u][i - 1]][i - 1];for (int e = H[u]; e; e = E[e].nt) { int v = E[e].to; if (v == fa) continue; me[v] = E[e].w; if (u != 1 && me[u] < me[v]) me[v] = me[u]; dfs1(v, u);  }
}
int lca(int u, int v) {if (dep[u] < dep[v]) swap(u, v);for (int i = BIT; ~i; i --) if (dep[f[u][i]] >= dep[v]) u = f[u][i]; if (u == v) return u;for (int i = BIT; ~i; i --) if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];return f[u][0];
}
void insert(int u) {if (top == 1) { stk[++ top] = u; return; }int Lca = lca(u, stk[top]);if (Lca == stk[top]) { stk[++ top] = u; return; }while (top > 1 && dfn[Lca] <= dfn[stk[top - 1]]) G[stk[top - 1]].push_back(stk[top]), -- top;if (Lca != stk[top]) G[Lca].push_back(stk[top]), stk[top] = Lca; stk[++ top] = u;
}
ll DP(int u) {ll res = 0;for (int i = 0; i < (int) G[u].size(); i ++) {int v = G[u][i]; res += min(me[v], DP(v));}G[u].clear(); if (ispoint[u]) return me[u]; else return res;
}
int main() {read(n);  for (int i = 1, u, v, w; i < n; i ++) { read(u); read(v); read(w); add_edge(u, v, w); add_edge(v, u, w);  }__dfn = 0; dfs1(1, 0);read(Q);while (Q --) {read(k);  for (int i = 1; i <= k; i ++) read(p[i]), ispoint[p[i]] = 1; sort(p + 1, p + 1 + k, cmp);  top = 0; stk[++ top] = 1; for (int i = 1; i <= k; i ++) insert(p[i]);while (top > 0) { G[stk[top - 1]].push_back(stk[top]); top --; } printf("%lld\n", DP(1));for (int i = 1; i <= k; i ++) G[p[i]].clear(), ispoint[p[i]] = 0; G[0].clear(); }return 0;
}

转载于:https://www.cnblogs.com/chhokmah/p/10695437.html

「洛谷2495」「BZOJ3052」「SDOI2001」消耗战【虚树+树形动态规划】相关推荐

  1. 「LuoguP4995」「洛谷11月月赛」 跳跳!(贪心

    题目描述 你是一只小跳蛙,你特别擅长在各种地方跳来跳去. 这一天,你和朋友小 F 一起出去玩耍的时候,遇到了一堆高矮不同的石头,其中第 ii 块的石头高度为 h_ihi​,地面的高度是 h_0 = 0 ...

  2. 【洛谷3345_BZOJ3924】[ZJOI2015]幻想乡战略游戏(点分树)

    大概有整整一个月没更博客了 -- 4 月为省选爆肝了一个月,最后压线进 B 队,也算给 NOIP2018 翻车到 316 分压线省一这个折磨了五个月的 debuff 画上了一个不算太差的句号.结果省选 ...

  3. 2019.03.21【ZJOI2007】【BZOJ1095】【洛谷P2056】Hide 捉迷藏(DFS序)(线段树)

    BZOJ传送门 洛谷传送门 解析: 其实就是QTREE4的弱化版,可以直接用QTREE4的解法来做. 但是这道题有优秀的O(nlog⁡n)O(n\log n)O(nlogn)做法. 我们考虑利用DFS ...

  4. 洛谷 P3380 bzoj3196 Tyvj1730 【模板】二逼平衡树(树套树)

    [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在 ...

  5. 「洛谷P1343」地震逃生 解题报告

    P1343 地震逃生 题目描述 汶川地震发生时,四川XX中学正在上课,一看地震发生,老师们立刻带领x名学生逃跑,整个学校可以抽象地看成一个有向图,图中有n个点,m条边.1号点为教室,n号点为安全地带, ...

  6. 「洛谷P2397」 yyy loves Maths VI (mode) 解题报告

    P2397 yyy loves Maths VI (mode) 题目背景 自动上次redbag用加法好好的刁难过了yyy同学以后,yyy十分愤怒.他还击给了redbag一题,但是这题他惊讶的发现自己居 ...

  7. 「洛谷P3469」[POI2008]BLO-Blockade 解题报告

    P3469[POI2008]LO-Blockade 题意翻译 在Byteotia有n个城镇. 一些城镇之间由无向边连接. 在城镇外没有十字路口,尽管可能有桥,隧道或者高架公路(反正不考虑这些).每两个 ...

  8. 「洛谷」P1406 方格填数

    P1406 方格填数 https://www.luogu.com.cn/problem/P1406 题目描述 给一个n 的方格矩阵,还有 n*n个整数,让你将这些整数填入矩阵,使得每行每列每个对角线上 ...

  9. 「洛谷 3768」简单的数学题

    传送门 problem 给定 nnn 和 ppp,求: ∑i=1n∑j=1nijgcd⁡(i,j)\sum_{i=1}^n\sum_{j=1}^nij\gcd(i,j)i=1∑n​j=1∑n​ijgc ...

最新文章

  1. Nature:人类肠道微生物组的肠型
  2. RNN和LSTM的正向/前向传播-图示公式和代码
  3. mysql物理读和逻辑读,SQL Server中STATISTICS IO物理读和逻辑读的误区
  4. 【视频课】先搞懂你用的模型,深度学习模型分析课程来了!
  5. POJ-2407 欧拉函数
  6. Team Foundation Server简介
  7. (13) css浮动补充
  8. php访问方法外变量
  9. C#枚举中使用Flags特性
  10. Linux 压缩与解压缩工具之zip
  11. 数据挖掘原理与实践学习(3)
  12. word排版之长英文单词自动换行
  13. python制作地图
  14. CodeForces 1037E Trips(瞎搞)
  15. 常见的服务器类型有哪些?
  16. linux trace 进程 文件路径,linux panic 问题定位
  17. NDK实践(一)在linux环境下编译ffmpe
  18. Java 实现顺时针螺旋二维数组输出
  19. Java中world、PDF、Excel转图片
  20. 视频号的发布技巧,视频号打造受欢迎的内容:国仁楠哥

热门文章

  1. Moment.js常见用法总结
  2. 【Fedora20】 samba配置
  3. POSIX风格正则表达式
  4. 显示当前行号、文件名和函数名(二)
  5. 微信小程序下拉刷新列表onPullDownRefresh;微信小程序上划加载列表onReachBottom;uni-app微信小程序下拉加载数据;uni-app微信小程序上划页面加载数据
  6. Java 结构体之 JavaStruct 使用教程二 JavaStruct 用例分析
  7. [react] 举例说明如何在React创建一个事件
  8. 手把手教你封装一个ant design的审核框组件
  9. React开发(110):注意state定义的数据类型
  10. [html] 使用button当按钮和使用div当按钮有什么区别?