题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2286

   https://www.luogu.org/problemnew/show/P2495

学习(抄)了 hzwer 的代码,觉得写得很好。http://hzwer.com/6188.html

有一个 “如果排序后第 i 个关键点和第 i-1 个关键点的 lca 是第 i-1 个关键点,就舍弃第 i 个关键点” 的操作,觉得很好。

把 hd[ ] 数组清空写在了 dfs 里,觉得很好。

自己一开始写了一个倍增找链上边权最小值,用来给虚树的边赋值,参考之后发现只要记录一个 “到根的路径上的最小边权” 就行了。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define ll long long
  5. using namespace std;
  6. int rdn()
  7. {
  8. int ret=;bool fx=;char ch=getchar();
  9. while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
  10. while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
  11. return fx?ret:-ret;
  12. }
  13. ll Mx(ll a,ll b){return a>b?a:b;}
  14. ll Mn(ll a,ll b){return a<b?a:b;}
  15.  
  16. const int N=,K=;const ll INF=3e10+;//for dp
  17. int n,hd[N],xnt,to[N<<],nxt[N<<],w[N<<];
  18. int dep[N],pre[N][K],bin[K],dfn[N],tim; ll mn[N];
  19. bool cmp(int a,int b){return dfn[a]<dfn[b];}
  20. void add(int x,int y,int z){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;}
  21. void dfs(int cr,int fa)
  22. {
  23. dfn[cr]=++tim; dep[cr]=dep[fa]+;
  24. pre[cr][]=fa;
  25. for(int t=;bin[t]<=dep[cr];t++)
  26. pre[cr][t]=pre[pre[cr][t-]][t-];
  27. for(int i=hd[cr],v;i;i=nxt[i])
  28. if((v=to[i])!=fa)
  29. {
  30. mn[v]=Mn(mn[cr],w[i]);
  31. dfs(v,cr);
  32. }
  33. }
  34. int get_lca(int x,int y)
  35. {
  36. if(dep[x]<dep[y])swap(x,y);
  37. int d=dep[x]-dep[y];
  38. for(int t=;bin[t]<=d;t++)
  39. if(d&bin[t])x=pre[x][t];
  40.  
  41. if(x==y)return x;
  42. for(int t=;t>=;t--)
  43. if(pre[x][t]!=pre[y][t])
  44. x=pre[x][t],y=pre[y][t];
  45. return pre[x][];
  46. }
  47. namespace Tr{
  48. int hd[N],xnt,to[N],nxt[N];
  49. int p[N],tot,sta[N],top; ll dp[N];
  50. void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
  51. void get_tr()
  52. {
  53. xnt=;
  54. sort(p+,p+tot+,cmp);
  55. int lm=tot; p[tot=]=p[];
  56. for(int i=;i<=lm;i++)
  57. if(get_lca(p[i],p[tot])!=p[tot])p[++tot]=p[i];
  58. sta[top=]=;
  59. for(int i=;i<=tot;i++)
  60. {
  61. int u=p[i], lca=get_lca(u,sta[top]);
  62. while(top&&dfn[lca]<dfn[sta[top]])
  63. {
  64. if(dfn[sta[top-]]<dfn[lca])
  65. add(lca,sta[top]);
  66. else add(sta[top-],sta[top]);
  67. top--;
  68. }
  69. if(sta[top]!=lca)sta[++top]=lca;
  70. sta[++top]=u;
  71. }
  72. for(int i=;i<top;i++)add(sta[i],sta[i+]);
  73. }
  74. void dfs(int cr)
  75. {
  76. if(!hd[cr]){dp[cr]=mn[cr];return;}
  77. dp[cr]=;
  78. for(int i=hd[cr],v;i;i=nxt[i])
  79. {
  80. dfs(v=to[i]); dp[cr]+=dp[v];
  81. }
  82. hd[cr]=;//////
  83. dp[cr]=Mn(dp[cr],mn[cr]);
  84. }
  85. void solve()
  86. {
  87. int k=rdn(); tot=;
  88. for(int i=,d;i<=k;i++)
  89. d=rdn(),p[++tot]=d;
  90. get_tr(); dfs(); printf("%lld\n",dp[]);
  91. }
  92. }
  93. int main()
  94. {
  95. bin[]=;for(int i=;i<=;i++)bin[i]=bin[i-]<<;
  96. n=rdn();
  97. for(int i=,u,v,z;i<n;i++)
  98. u=rdn(),v=rdn(),z=rdn(),add(u,v,z),add(v,u,z);
  99. mn[]=INF; dfs(,);
  100. int Q=rdn(); while(Q--)Tr::solve();
  101. return ;
  102. }

bzoj 2286(洛谷 2495) [Sdoi2011]消耗战——虚树的更多相关文章

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

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一 ...

  2. BZOJ.2286.[SDOI2011]消耗战(虚树 树形DP)

    题目链接 BZOJ 洛谷P2495 树形DP,对于每棵子树要么逐个删除其中要删除的边,要么直接断连向父节点的边. 如果当前点需要删除,那么直接断不需要再管子树. 复杂度O(m*n). 对于两个要删除的 ...

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

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

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

    P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...

  5. BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序

    https://www.lydsy.com/JudgeOnline/problem.php?id=2286 wa了两次因为lca犯了zz错误 这道题如果不多次询问的话就是裸dp. 一棵树上多次询问,且 ...

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

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

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

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

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

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

  9. BZOJ 2286 [Sdoi2011]消耗战 ——虚树

    虚树第一题. 大概就是建一颗只与询问有关的更小的新树,然后在虚树上DP #include <map> #include <ctime> #include <cmath&g ...

随机推荐

  1. oracle12c中新能优化新特性之热度图和自动数据优化

    1. Oracle12c热度图和自动数据优化 信息生命周期管理(ILM)是指在数据生命周期内管理它们的策略.依赖于数据的年龄和对应用的业务相关性,数据能被压缩,能被归档或移到低成本的存储上.简言之,I ...

  2. for each...in,for...in, for...of

    一.for  each ...in explanation: 该语句在对象属性的所有值上迭代指定的变量.对于每个不同的属性,执行指定的语句. 句法: for each (variable in obj ...

  3. poj3020 二分图匹配 最大独立集

    这是一道水题, 这里是最大流解法,之后再补 坑在又忘了反向建边了 题意:给你二维bool数组,让你求出能用多米诺骨牌覆盖所有 1 且骨牌最少的放法(因为多米诺骨牌1*2的结构方便描述,原题没有),原本 ...

  4. scrapy的selectors

    from scrapy import Selector >>> doc = """ ... <div> ...     <ul> ...

  5. 1.3 C++引用(Reference)

    参考:http://www.weixueyuan.net/view/6328.html 总结: 引用是变量的另外一个别名,不是指针,与原变量名同指相同的内存.可以原变量的值. 在函数中作为形参可以修改 ...

  6. ABP .Net Core 调用异步方法抛异常A second operation started on this context before a previous asynchronous operation completed

    1.  问题描述 最近使用ABP .Net Core框架做一个微信开发,同时采用了一个微信开发框架集成到ABP,在微信用户关注的推送事件里调用了一个async 方法,由于没有返回值,也没做任何处理,本 ...

  7. 2.3 linux中的信号分析 阻塞、未达

    信号的阻塞.未达: linux中进程1向进程2发送信号,要经过内核,内核会维护一个进程对某个信号的状态,如下图所示: 当进程1向进程2发送信号时,信号的传递过程在内核中是有状态的,内核首先要检查这个信 ...

  8. LMS算法

    一.感知器算法和LMS算法 感知器和自适应线性元件在历史上几乎是同时提出的,并且两者在对权值的调整的算法非常相似.它们都是基于纠错学习规则的学习算法. 感知器算法存在如下问题:不能推广到一般的前向网络 ...

  9. mac 搭建Vue开发环境

    1: 使用的各个工具的版本为: Homebrew 1node.js npm  webpack Vue 2: 安装brew 打开终端运行一下命令 /usr/bin/ruby -e "$(cur ...

  10. Windows Security Login

    /********************************************************************************* * Windows Securit ...