题目

【题目描述】

在一场战争中,战场由 $n$ 个岛屿和 $n-1$ 个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为 $1$ 的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他 $k$ 个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。

侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到 $1$ 号岛屿上)。不过侦查部门还发现了这台机器只能够使用 $m$ 次,所以我们只需要把每次任务完成即可。

【输入格式】

第一行一个整数 $n$ ,代表岛屿数量。

接下来 $n-1$ 行,每行三个整数 $u,v,w$ ,代表 $u$ 号岛屿和 $v$ 号岛屿由一条代价为 $c$ 的桥梁直接相连,保证 $1 \le u,v \le n$ 且 $1 \le c \le 100000 $ 。

第 $n+1$ 行,一个整数 $m$ ,代表敌方机器能使用的次数。

接下来 $m$ 行,每行一个整数 $k_i$ ,代表第 $i$ 次后,有 $k_i$ 个岛屿资源丰富,接下来 $k$ 个整数$h_1,h_2,…h_k$ ,表示资源丰富岛屿的编号。

【输出格式】
输出有 $m$ 行,分别代表每次任务的最小代价。
【样例输入】

10
1 5 13
1 9 6
2 1 19
2 4 8
2 3 91
5 6 8
7 5 4
7 8 31
10 7 9
3
2 10 6
4 5 7 8 3
3 9 4 6

【样例输出】

12
32
22

【数据范围与提示】
对于100%的数据, $2 \le n \le 250000,m \ge 1, \sum{k_i} \le 500000,1 \le k_i \le n-1 $

题解

考虑树形 dp,记 $ g[i] $ 表示将 $ i $ 及其子树断开的最小代价,然后发现效率过不去

因为 $ \sum k \leq 5 \times 10^5 $,考虑构造虚树,然后直接 dp 即可

时间效率:$ O(2\log n\times \sum k) $,因为一棵虚树最多只有 $ 2k $ 个点,查询 LCA 的效率为 $ O(\log n) $

构造虚树:https://www.cnblogs.com/zwfymqz/p/9175152.html

代码

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. #define pb push_back
  4. #define _(d) while(d(isdigit(ch=getchar())))
  5. using namespace std;
  6. int R(){
  7. int x;bool f=;char ch;_(!)if(ch=='-')f=;x=ch^;
  8. _()x=(x<<)+(x<<)+(ch^);return f?x:-x;}
  9. const int N=2.5e5+;
  10. int n,m,f[N][],head[N],cnt,dfn[N],dep[N],a[N],sta[N],top,tot,lg;
  11. LL g[N];
  12. vector<int>G[N];
  13. struct edge{int to,nex;LL w;}e[N<<];
  14. bool cmp(int a,int b){return dfn[a]<dfn[b];}
  15. void add(int s,int t,int w){e[++cnt]=(edge){t,head[s],w},head[s]=cnt;}
  16. void dfs(int u,int far){
  17. dfn[u]=++tot,f[u][]=far,dep[u]=dep[far]+;
  18. for(int i=;i<=lg;i++)f[u][i]=f[f[u][i-]][i-];
  19. for(int k=head[u],v;k;k=e[k].nex)
  20. if((v=e[k].to)!=far)
  21. g[v]=min(g[u],e[k].w),dfs(v,u);
  22. }
  23. int lca(int x,int y){
  24. if(dep[x]>dep[y])swap(x,y);
  25. int i=lg;
  26. while(dep[x]<dep[y]){
  27. while(i&&dep[x]>dep[f[y][i]])i--;
  28. y=f[y][i];}
  29. i=lg;
  30. while(x!=y){
  31. while(i>&&f[x][i]==f[y][i])i--;
  32. x=f[x][i],y=f[y][i];}
  33. return x;
  34. }
  35. void insert(int x){
  36. if(top==){sta[++top]=x;return;}
  37. int far=lca(x,sta[top]);
  38. if(far==sta[top])return;
  39. while(top>&&dfn[sta[top-]]>=dfn[far])
  40. G[sta[top-]].pb(sta[top]),top--;
  41. if(far!=sta[top])G[far].pb(sta[top]),sta[top]=far;
  42. sta[++top]=x;
  43. return;
  44. }
  45. LL work(int x){
  46. if(!G[x].size())return g[x];
  47. LL sum=;
  48. for(int i=G[x].size()-;~i;i--)
  49. sum+=work(G[x][i]);
  50. G[x].clear();
  51. return min(sum,(LL)g[x]);
  52. }
  53. int main(){
  54. memset(g,0x3f,sizeof g);
  55. n=R(),lg=log2(n)+;
  56. for(int i=,u,v,w;i<n;i++)
  57. u=R(),v=R(),w=R(),add(u,v,w),add(v,u,w);
  58. dfs(,);
  59. for(int q=R();q--;){
  60. m=R();
  61. for(int i=;i<=m;i++)a[i]=R();
  62. sort(a+,a++m,cmp);
  63. sta[top=]=;
  64. for(int i=;i<=m;i++)insert(a[i]);
  65. while(top)G[sta[top-]].pb(sta[top]),top--;
  66. printf("%lld\n",work());
  67. }
  68. return ;
  69. }

消耗战——dp+虚树的更多相关文章

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

    传送门 题意: 删除价值和最小的边使得$1$号点与$k$个关键点不连通 一个树形DP...但是询问多次,保证总的关键点数为$O(n)$ 先说一下这个$DP$ $f[i]$表示子树$i$中的关键点与$1 ...

  2. BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca

    BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...

  3. 【BZOJ2286】消耗战(虚树,动态规划)

    [BZOJ2286]消耗战(虚树,动态规划) 题面 BZOJ Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总 ...

  4. [SDOI2011]消耗战(虚树)

    洛古题面 题意:给定一棵树,割断每一条边都有代价,每次询问会给定一些点,求用最少的代价使所有给定点都和1号节点不连通 暴力\(DP\) 我们先考虑暴力怎么做 设\(dp[u]\)为以\(u\)为根的子 ...

  5. BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 4261  Solved: 1552 [Submit][Sta ...

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

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

  7. 虚树+【BZOJ2286】【SDOI2011】消耗战(虚树)(DP)

    先看一道题: [BZOJ2286][SDOI2011]消耗战 Description 在一场战争中,战场由n个岛屿和n−1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总 ...

  8. bzoj 2286 [Sdoi2011]消耗战(虚树+树上DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题意] 给定一棵树,切断一条树边代价为ci,有m个询问,每次问使得1号点与查询 ...

  9. 2018.09.25 bzoj2286: [Sdoi2011]消耗战(虚树+树形dp)

    传送门 又一道虚树入门题. 这个dp更简单啊. 直接记录每个点到1的距离,简单转移就行了. 代码: #include<bits/stdc++.h> #define N 250005 #de ...

随机推荐

  1. 与STL文件相关的各类学习地址

    几个网址: 1.STL :https://en.wikipedia.org/wiki/STL_(file_format)#ASCII_STL 2.一个博客的文章地址: 三维图形数据格式 STL的 读取 ...

  2. Django 模版当中使用中文 UnicodeDecodeError at / 问题

    Django 再次是当中字符编码问题 今天使用了bootstrap 当中的一些CSS 对自己的博客项目当中的一些东西进行美化 但是很奇怪的是 当 诸如按钮类的加入 中文字符后 就会提示 Unicode ...

  3. css3加载spinner

    使用代码制作一个加载旋转器spinner 实现的原理是: 1.两个圆圈,其中一个圆圈是使用pseudo元素(:before)产生 2.由pseudo元素生成的圆通过负数的z-index而作用在下面 3 ...

  4. COM组件的集合与包容

    集合与包容,实质就是组件之间的互相调用.即一个组件使用另一个组件的功能,达到代码复用的作用.只是这种复用是构建在二进制数据上的(因为被复用的组件常常以dll的格式存在),而不是像c++代码复用是以源文 ...

  5. Java中常见的几个乱码问题以及解决方法

    1.ajax--URL中的参数含中文,后台接受的参数出现乱码 解决方法: 第一步:在javascript中,对url进行两次编码 url = "http://localhost:8080/M ...

  6. type_traits.h

    type_traits.h // Filename: type_traits.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ht ...

  7. Struts2 - 通过 ActionContext 访问 Web 资源

    public String execute(){ //0. 获取 ActionContext 对象 //ActionContext 是 Action 的上下文对象. 可以从中获取到当往 Action ...

  8. Smali文件添加try/catch语句,出现“invalid use of move-exception”异常

    插入代码如下: 捕获到以下异常: 2019-03-18 21:09:35.431 8272-8272/com.xxxx.xxxx E/AndroidRuntime: FATAL EXCEPTION: ...

  9. ACM学习历程—SNNUOJ1132 余数之和(数论)

    Description F(n) = (n % 1) + (n % 2) + (n % 3) + ...... (n % n).其中%表示Mod,也就是余数.例如F(6) = 6 % 1 + 6 % ...

  10. 洛谷 P2777 [AHOI2016初中组]自行车比赛

    题目描述 小雪非常关注自行车比赛,尤其是环滨湖自行车赛.一年一度的环滨湖自行车赛,需要选手们连续比赛数日,最终按照累计得分决出冠军.今年一共有 N 位参赛选手.每一天的比赛总会决出当日的排名,第一名的 ...