【题意】给定n个点的带边权树,每次询问给定ki个特殊点,求隔离点1和特殊点的最小代价。n<=250000,Σki<=500000。

【算法】虚树+DP

【题解】考虑普通树上的dp,设f[x]表示隔离1和子树x内特殊点的最小代价,val[x]表示x到1路径上的最小代价(预处理)。

点x特殊,f[x]=val[x]

否则,f[x]=min{val[x],Σf[y]},y=son[x]

在询问总数有限制的前提下,可以建虚树进行如上DP。

复杂度O(Σki log n)。

注意:

1.清空时垃圾回收,保证复杂度。

2.询问点数组开两倍,因为要加入两两LCA。

  1. #include<cstdio>
  2. #include<cctype>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define ll long long
  6. using namespace std;
  7. int read(){
  8. int s=,t=;char c;
  9. while(!isdigit(c=getchar()))if(c=='-')t=-;
  10. do{s=s*+c-'';}while(isdigit(c=getchar()));
  11. return s*t;
  12. }
  13. const int maxn=;
  14. struct edge{int v,w,from;}e[maxn*];
  15. int in[maxn],ou[maxn],deep[maxn],f[maxn][],st[maxn],n,N,tot,first[maxn],a[maxn*];//a[]
  16. bool v[maxn];
  17. ll val[maxn];
  18.  
  19. namespace cyc{
  20. struct edge{int v,w,from;}e[maxn*];
  21. int first[maxn],dfsnum=,tot;
  22. void insert(int u,int v,int w){tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
  23. void dfs(int x,int fa){
  24. in[x]=++dfsnum;
  25. for(int j=;(<<j)<=deep[x];j++)f[x][j]=f[f[x][j-]][j-];
  26. for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
  27. deep[e[i].v]=deep[x]+;
  28. val[e[i].v]=min(val[x],1ll*e[i].w);
  29. f[e[i].v][]=x;
  30. dfs(e[i].v,x);
  31. }
  32. ou[x]=dfsnum;
  33. }
  34. int lca(int x,int y){
  35. if(deep[x]<deep[y])swap(x,y);
  36. int d=deep[x]-deep[y];
  37. for(int i=;i<=;i++)if((<<i)&d)x=f[x][i];
  38. if(x==y)return x;
  39. for(int i=;i>=;i--)if((<<i)<=deep[x]&&f[x][i]!=f[y][i]){
  40. x=f[x][i];y=f[y][i];
  41. }
  42. return f[x][];
  43. }
  44. void build(){
  45. n=read();
  46. for(int i=;i<n;i++){
  47. int u=read(),v=read(),w=read();
  48. insert(u,v,w);insert(v,u,w);
  49. }
  50. val[]=1ll<<;//
  51. dfs(,-);
  52. }
  53. }
  54. void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
  55. bool cmp(int a,int b){return in[a]<in[b];}
  56. ll dp(int x){
  57. if(v[x])return val[x];
  58. ll sum=;
  59. for(int i=first[x];i;i=e[i].from)sum+=dp(e[i].v);
  60. return min(val[x],sum);
  61. }
  62. bool check(int x,int y){return in[y]<=in[x]&&ou[x]<=ou[y];}
  63. void build(){
  64. int last=read();N=last;
  65. for(int i=;i<=N;i++)a[i]=read(),v[a[i]]=;//
  66. sort(a+,a+N+,cmp);
  67. for(int i=;i<last;i++)a[++N]=cyc::lca(a[i],a[i+]);
  68. sort(a+,a+N+,cmp);
  69. N=unique(a+,a+N+)-a-;
  70. for(int i=;i<=N;i++)first[a[i]]=;tot=;//
  71. int top=;
  72. for(int i=;i<=N;i++){
  73. while(top&&!check(a[i],st[top]))top--;
  74. if(top)insert(st[top],a[i]);
  75. st[++top]=a[i];
  76. }
  77. printf("%lld\n",dp(a[]));
  78. for(int i=;i<=N;i++)v[a[i]]=;//
  79. }
  80. int main(){
  81. cyc::build();
  82. int m=read();
  83. while(m--)build();
  84. return ;
  85. }

【BZOJ】2286: [Sdoi2011]消耗战 虚树+DP的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. BZOJ 2286: [Sdoi2011]消耗战 虚树

    Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军 ...

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

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

  8. BZOJ 2286: [Sdoi2011]消耗战

    2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2082  Solved: 736[Submit][Status] ...

  9. BZOJ 3572 [HNOI2014]世界树 (虚树+DP)

    题面:BZOJ传送门 洛谷传送门 题目大意:略 细节贼多的虚树$DP$ 先考虑只有一次询问的情况 一个节点$x$可能被它子树内的一个到x距离最小的特殊点管辖,还可能被管辖fa[x]的特殊点管辖 跑两次 ...

随机推荐

  1. hdu 1907 (尼姆博弈)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1907 Problem Description Little John is playing very ...

  2. 群福利:Redis云服务器免费领取(附Redis安装和连接远程连接Redis案例)

    Redis安装:在线体验:https://try.redis.io Ubuntu:sudo apt-get install redis CentOS:yum install redis (root权限 ...

  3. 【SDOI2008】仪仗队

    //裸的欧拉函数//y=kx//求不同的k有多少#include<bits/stdc++.h> #define ll long long #define N 40010 using nam ...

  4. Django(十二)—关于查询知识点总结

    https://www.cnblogs.com/haiyan123/p/7763710.html models.Book.objects.filter(**kwargs):   querySet   ...

  5. Gym - 101911A "Coffee Break"

    传送门 题意: Monocarp得到一份工作,每天要工作 m 分钟,他有一个爱好,喜欢在休息的时候喝咖啡,但是他的老板不乐意了,就给他规定了个 时间 d,在 d 分钟内只能喝一杯咖啡. 现给出Mono ...

  6. gradle 的jar下载到哪里了

    很好奇 gradle 的jar下载到哪里了,好顿翻,原来在C:\Users\(你的用户名)\.gradle\caches\modules-2\files-2.1目录下,使用gradle引用lib会先查 ...

  7. python自动化开发-[第八天]-面向对象高级篇与网络编程

    今日概要: 一.面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) 2.__setattr__,__getattr__,__delattr__ 3.二 ...

  8. org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].Standard

    Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lan ...

  9. JavaSE_坚持读源码_HashMap对象_get_Java1.7

    当你从HashMap里面get时,你其实在干什么? /** * Returns the value to which the specified key is mapped, * or {@code ...

  10. JavaSE_坚持读源码_Object对象_Java1.7

    /** * Returns a hash code value for the object. This method is * supported for the benefit of hash t ...