BZOJ2286:[SDOI2011]消耗战(树形DP,虚树)

BZOJ2286:[SDOI2011]消耗战(树形DP,虚树)

Description

在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。
侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到1号岛屿上)。不过侦查部门还发现了这台机器只能够使用m次,所以我们只需要把每次任务完成即可。

Input

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

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

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

接下来m行,每行一个整数ki,代表第i次后,有ki个岛屿资源丰富,接下来k个整数h1,h2,…hk,表示资源丰富岛屿的编号。

Output

输出有m行,分别代表每次任务的最小代价。

Sample Input

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

Sample Output

12

32

22

HINT

对于100%的数据,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1

Solution

虚树真是个好东西啊QAQ

推荐博客

建议对虚树的理解看第一个,构建看第二个QAQ

题解去看第二个吧我也懒得写了XD

顺带提一句因为本题特殊,所以建虚树的时候要写成57行那样,否则就把57行删掉改成58行就行了。

至于本题为什么要像57行那么写呢……

假设$x$点是$y$的祖先,如果$x$到根不连通,那么$y$到根一定不连通,所以$y$点也就没有加进去的必要了。而且加进去的话像我这样$DP$也就不对了啊啊QAQQQQ

Code

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<vector>
  6 #define N (250009)
  7 #define LL long long
  8 using namespace std;
  9 
 10 struct Edge{
   int to,next,len;}edge[N<<1];
 11 int n,m,k,u,v,l,dfs_num;
 12 int a[N],Depth[N],f[N][19],DFN[N];
 13 LL Min[N];
 14 int head[N],num_edge;
 15 
 16 void add(int u,int v,int l)
 17 {
 18     edge[++num_edge].to=v;
 19     edge[num_edge].next=head[u];
 20     edge[num_edge].len=l;
 21     head[u]=num_edge;
 22 }
 23 
 24 void DFS(int x,int fa)
 25 {
 26     f[x][0]=fa;
 27     for (int i=1; i<=18; ++i) f[x][i]=f[f[x][i-1]][i-1];
 28     DFN[x]=++dfs_num; Depth[x]=Depth[fa]+1;
 29     for (int i=head[x]; i; i=edge[i].next)
 30         if (edge[i].to!=fa)
 31         {
 32             Min[edge[i].to]=min(Min[x],(LL)edge[i].len);
 33             DFS(edge[i].to,x);
 34         }
 35 }
 36 
 37 int LCA(int x,int y)
 38 {
 39     if (Depth[x]<Depth[y]) swap(x,y);
 40     for (int i=18; i>=0; --i)
 41         if (Depth[f[x][i]]>=Depth[y]) x=f[x][i];
 42     if (x==y) return x;
 43     for (int i=18; i>=0; --i)
 44         if (f[x][i]!=f[y][i]) x=f[x][i], y=f[y][i];
 45     return f[x][0]; 
 46 }
 47 
 48 vector<int>E[N];
 49 void ADD(int x,int y) {E[x].push_back(y);}
 50 int stack[N],top;
 51 bool cmp(int x,int y) {
   return DFN[x]<DFN[y];}
 52 
 53 void Insert(int x)
 54 {
 55     if (top==1) {stack[++top]=x; return;}
 56     int lca=LCA(x,stack[top]);
 57     if (lca==stack[top]) return;
 58 //    if (lca==stack[top]) {stack[++top]=x; return;}
 59     while (top>1 && DFN[stack[top-1]]>=DFN[lca])
 60         ADD(stack[top-1],stack[top]), top--;
 61     if (lca!=stack[top]) ADD(lca,stack[top]), stack[top]=lca;
 62     stack[++top]=x;
 63 }
 64 
 65 void Build()
 66 {
 67     stack[top=1]=1;
 68     for (int i=1; i<=k; ++i) Insert(a[i]);
 69     while (top>=2) ADD(stack[top-1],stack[top]), top--;
 70 }
 71 
 72 LL DP(int x)
 73 {
 74     int sz=E[x].size();
 75     if (!sz) return Min[x];
 76     LL ans=0;
 77     for (int i=0; i<sz; ++i)
 78         ans+=DP(E[x][i]);
 79     E[x].clear();
 80     return min(ans,Min[x]);
 81 }
 82 
 83 int main()
 84 {
 85     Min[1]=1e18;
 86     scanf("%d",&n);
 87     for (int i=1; i<=n-1; ++i)
 88     {
 89         scanf("%d%d%d",&u,&v,&l);
 90         add(u,v,l); add(v,u,l);
 91     }
 92     DFS(1,0);
 93     scanf("%d",&m);
 94     for (int i=1; i<=m; ++i)
 95     {
 96         scanf("%d",&k);
 97         for (int j=1; j<=k; ++j) scanf("%d",&a[j]);
 98         sort(a+1,a+k+1,cmp);
 99         Build();
100         printf("%lld\n",DP(1));
101     }
102 }

转载于:https://www.cnblogs.com/refun/p/10064045.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101285.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • string 转 map_一二段转奶的正确方法

    string 转 map_一二段转奶的正确方法String转Map方法很久没写java了,今天有个map传过来格式变成String了需要转map,本来应该可以找个简单的方式解决,但我就不相信找不到了,最后找了半天都没成功的。。。然后自己写了个小方法分享一下仅限以下格式转map{a=aaa,b=bbb,c=ccc,d=ddd,e=eee}publicstaticMap<String,Object>StringToMap(Stringparam){Map<String,Object

    2022年9月11日
    0
  • navcat15 for mysql激活码 3月最新注册码

    navcat15 for mysql激活码 3月最新注册码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月14日
    40
  • 海康威视摄像头不支持的码流类型_v380pro摄像头怎么连接无线网

    海康威视摄像头不支持的码流类型_v380pro摄像头怎么连接无线网前言:对于HIS视频采集、输出和编解码,直接使用海思SDK中的sample代码+NVP6124就可以实现,这里有提供HIMPP开发文档、海思sample源码和NVP6124的驱动代码,可以自行去下载;HIMPP开发文档:https://download.csdn.net/download/u012478275/11573292海思sample源码:…

    2022年9月23日
    0
  • AArch64教程第一章

    AArch64教程第一章AArch64教程第一章AArch64是一个新的64位模式,它是ARMv8架构下的一部分,它于2011年随着ARM发布。它被逐步部署于智能手机和服务器。所以我认为现在学习一点关于此架构的知识是比较好的。硬件目前,有ARMv6/ARMv7的单板电脑是比较容易获得的,其中最流行的一个选择是树莓派。相反,支持64位ARMv8模式的单板电脑就没有那么多了,但是它们最近也慢慢变得流行了起来。例如,Pine64,ODROID-C2,Dragonboard410c,等等。它们中的任何一种都可以做64位开发,

    2022年10月16日
    0
  • CORBA简介_吴帝聪简介

    CORBA简介_吴帝聪简介 1.CORBA:CommonObjectRequestBrokerArchitecture,通用对象请求代理体系。是由对象管理组(ObjectManagementGroup,OMG)制定的一种标准的面向对象分布式应用程序体系规范,旨在为异构分布式环境中,硬件和软件系统的互联而提出的一种解决方案。2.解决异构分布式系统两条主要原则:(1).寻求独立于平台的模型和抽象,这

    2022年4月19日
    48
  • 华为c++面试题和答案汇总_C语言经典笔试题

    华为c++面试题和答案汇总_C语言经典笔试题《几道华为经典C语言面试题》由会员分享,可在线阅读,更多相关《几道华为经典C语言面试题(6页珍藏版)》请在人人文库网上搜索。1、1、找错voidtest1()charstring10;char*str1=;strcpy(string,str1);这里string数组越界,因为字符串长度为10,还有一个结束符0。所以总共有11个字符长度。string数组大小为10,这里越界了。PS:使用st…

    2022年8月28日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号