P2495 [SDOI2011]消耗战

题目链接

题解:

虚树\(dp\)入门题吧。虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是一样的,所以可以就求出dfs序并且利用它来构造。最后的图中只有关键点以及某些关键点对的lca。

具体构造方法就是利用一个栈,假设当前插入结点为\(x\),求出栈顶元素和\(x\)的lca,如果栈顶元素为lca,那么我们就继续延长这条链;否则(此时栈顶元素和\(x\)在lca的两颗子树上面)就将栈顶元素到\(lca\)上面的点弹出来并且建边,然后继续延长\(x\)这边的链。

感觉说得不是很清楚,详见代码吧:

  1. #include <bits/stdc++.h>
  2. #define INF 0x3f3f3f3f
  3. using namespace std;
  4. typedef long long ll;
  5. const int N = 250005 ;
  6. int n, m;
  7. struct Edge{
  8. int v, next, w;
  9. }e[N << 1];
  10. int head[N], tot;
  11. void adde(int u, int v, int w) {
  12. e[tot].v = v; e[tot].w = w; e[tot].next = head[u]; head[u] = tot++;
  13. }
  14. vector <int> g[N] ;
  15. int f[N][20], deep[N], dfn[N];
  16. ll mn[N];
  17. int T;
  18. void dfs(int u, int fa) {
  19. deep[u] = deep[fa] + 1;
  20. dfn[u] = ++T;
  21. for(int i = head[u]; i != -1; i = e[i].next) {
  22. int v = e[i].v;
  23. if(v == fa) continue ;
  24. mn[v] = min((ll)e[i].w, mn[u]) ;
  25. f[v][0] = u;
  26. for(int j = 1; j <= 17; j++) f[v][j] = f[f[v][j - 1]][j - 1] ;
  27. dfs(v, u) ;
  28. }
  29. }
  30. int LCA(int x, int y) {
  31. if(deep[x] < deep[y]) swap(x, y) ;
  32. for(int i = 17; i >= 0; i--) {
  33. if(deep[f[x][i]] >= deep[y]) x = f[x][i] ;
  34. }
  35. if(x == y) return x;
  36. for(int i = 17; i >= 0; i--) {
  37. if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i] ;
  38. }
  39. return f[x][0] ;
  40. }
  41. int sta[N], a[N];
  42. int top;
  43. bool cmp(const int &x, const int &y) {
  44. return dfn[x] < dfn[y] ;
  45. }
  46. void add_edge(int u, int v) {
  47. g[u].push_back(v) ;
  48. }
  49. void insert(int x) {
  50. int lca = LCA(x, sta[top]) ;
  51. if(top == 1) {sta[++top] = x; return ;}
  52. if(lca == sta[top]) return ;
  53. while(top > 1 && dfn[sta[top - 1]] >= dfn[lca]) {
  54. add_edge(sta[top - 1], sta[top]); top--;
  55. }
  56. if(sta[top] != lca) add_edge(lca, sta[top]), sta[top] = lca;
  57. sta[++top] = x;
  58. }
  59. ll DP(int u) {
  60. if(g[u].size() == 0) return mn[u];
  61. ll sum = 0;
  62. for(auto v : g[u]) sum += DP(v) ;
  63. g[u].clear() ;
  64. return min(sum, (ll)mn[u]) ;
  65. }
  66. int main() {
  67. ios::sync_with_stdio(false); cin.tie(0);
  68. cin >> n;
  69. mn[1] = 1ll << 56;
  70. memset(head, -1, sizeof(head)) ;
  71. for(int i = 1; i < n; i++) {
  72. int u, v, w;
  73. cin >> u >> v >> w;
  74. adde(u, v, w); adde(v, u, w) ;
  75. }
  76. dfs(1, 0) ;
  77. cin >> m;
  78. while(m--) {
  79. int k; cin >> k;
  80. for(int i = 1; i <= k; i++) cin >> a[i] ;
  81. sort(a + 1, a + k + 1, cmp) ;
  82. sta[top = 1] = 1;
  83. for(int i = 1; i <= k; i++) insert(a[i]) ;
  84. while(top > 1) add_edge(sta[top - 1], sta[top]), top--;
  85. cout << DP(1) << '\n' ;
  86. }
  87. return 0 ;
  88. }

洛谷P2495 [SDOI2011]消耗战(虚树dp)的更多相关文章

  1. bzoj 2286(洛谷 2495) [Sdoi2011]消耗战——虚树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2286 https://www.luogu.org/problemnew/show/P2495 ...

  2. 洛谷 P2495 [SDOI2011]消耗战(虚树,dp)

    题面 洛谷 题解 虚树+dp 关于虚树 了解一下 具体实现 inline void insert(int x) { if (top == 1) {s[++top] = x; return ;} int ...

  3. [BZOJ2286][SDOI2011]消耗战(虚树DP)

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4998  Solved: 1867[Submit][Statu ...

  4. ●洛谷P2495 [SDOI2011]消耗战

    题链: https://www.luogu.org/problemnew/show/P2495题解: 虚树入门,树形dp 推荐博客:http://blog.csdn.net/lych_cys/arti ...

  5. bzoj 2286 [Sdoi2011]消耗战 虚树+dp

    题目大意:多次给出关键点,求切断边使所有关键点与1断开的最小费用 分析:每次造出虚树,dp[i]表示将i和i子树与父亲断开费用 对于父亲x,儿子y ①y为关键点:\(dp[x]\)+=\(dismn( ...

  6. 【BZOJ】2286: [Sdoi2011]消耗战 虚树+DP

    [题意]给定n个点的带边权树,每次询问给定ki个特殊点,求隔离点1和特殊点的最小代价.n<=250000,Σki<=500000. [算法]虚树+DP [题解]考虑普通树上的dp,设f[x ...

  7. 洛谷P2495 [SDOI2011]消耗战(虚树)

    题面 传送门 题解 为啥一直莫名其妙\(90\)分啊--重构了一下代码才\(A\)掉-- 先考虑直接\(dp\)怎么做 树形\(dp\)的时候,记一下断开某个节点的最小值,就是从根节点到它的路径上最短 ...

  8. [洛谷P2495][SDOI2011]消耗战

    题目大意:有一棵$n(n\leqslant2.5\times10^5)$个节点的带边权的树,$m$个询问,每次询问给出$k(\sum\limits_{i=1}^mk_i\leqslant5\times ...

  9. 洛谷 P3233 [HNOI2014]世界树(虚树+dp)

    题面 luogu 题解 数据范围已经告诉我们是虚树了,考虑如何在虚树上面\(dp\) 以下摘自hzwer博客: 构建虚树以后两遍dp处理出虚树上每个点最近的议事处 然后枚举虚树上每一条边,考虑其对两端 ...

随机推荐

  1. Linux内核文档翻译——kobject.txt

    ==================================================================== Everything you never wanted to ...

  2. Functional-Light-JS 摘录笔记(1)

    function foo(...args) { console.log( args[3] ); } var arr = [ 1, 2, 3, 4, 5 ]; foo( ...arr ); Think ...

  3. 原始(Prototype)模式

    原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型对象创建新的对象. 原型模式其实就是从一个对象创建另外一个可复制的对象,而且不需要知道任何创建的细节.(最常用的就是基于流的深复制) 原始模 ...

  4. 一、docker 入坑(win10和Ubuntu 安装)

    前言 终究还是绕不过去了,要学的知识真的是太多了,好在我们还有时间,docker 之前只闻其声,不曾真正的接触过,现在docker 越来越火,很多公司也都开始使用了.所以对于我们程序员而言,又得修炼一 ...

  5. 100道MySQL常见面试题总结

    原文链接:https://juejin.im/post/5d351303f265da1bd30596f9 前言 本文主要受众为开发人员,所以不涉及到MySQL的服务部署等操作,且内容较多,大家准备好耐 ...

  6. Stopwatch 类用于计算程序运行时间

    Stopwatch 类 命名空间:System.Diagnostics.Stopwatch 实例化:Stopwatch getTime=new Stopwatch(); 开始计时:getTime.St ...

  7. Entity Framework 学习系列(3) - MySql Code First 开发方式+数据迁移

    目录 # 写在前面 一.开发环境 二.创建项目 三.安装程序包 四.创建模型 五.连接字符串 六.编辑程序 七.数据迁移 写在最后 # 写在前面 这几天,一直都在学习Entity Framework ...

  8. drf--ModelSerializers序列化

    目录 drf--ModelSerializers序列化 项目准备 配置 settings.py 路由 多表设计 表关系分析 创建models 模型序列化 自定义模型序列化 api/serializer ...

  9. SAP HANA学习资料大全 Simple Finane + Simple Logisitic [非常完善的学习资料汇总]

    Check out this SDN blog if you plan to write HANA Certification exam http://scn.sap.com/community/ha ...

  10. 2019-08-01 JQuery事件

    Jquery简单的事件 l blur(fn) 当失去焦点时 l change(fn) 当内容发生改变时 l click(fn) 当鼠标单击时 l dblclick 当鼠标双击时 l focus(fn) ...