BZOJ2286: [Sdoi2011]消耗战(虚树)


BZOJ2286: [Sdoi2011]消耗战

  Time Limit: 20 Sec
  Memory Limit: 512 MB

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
  

题目地址:  BZOJ2286: [Sdoi2011]消耗战

题目大意: 已经很简洁了

题解:

  裸的虚树
  
  虚树的概念
  虚树,就是在有一棵树的情况下,对于数量较少的点进行询问时所建的一棵新的树,虚树包含询问的点和询问的点的lca(最近公共祖先),上面的点被称为关键点。对于两个关键点A,B,它们的连边上包含着原本树上两点之间那条链上的关键信息(这个信息可以是边权最大值、边权最小值、或者是边权之和,这个取决于实际需要),然后就可以进行树形dp了,这样的复杂度是基于询问的点数的,就可以想象虚树就是把一棵大树浓缩成一棵拥有所有你需要的信息的小树。
  
  建树的方法
那么怎么建树呢,比较常见的做法是维护一个栈,里面存储着一条链,每一次加入一个点进行操作。
具体列举一下步骤吧
  
  预备知识:
  用较优的复杂度求lca,以及求两点之间的距离,一般倍增做,或者树链剖分加前缀和都可以,这都是单次O(logn)的,另外呢,要事先求好原树的dfs序和每个点的深度(这里的深度是指点序的深度,在计算这个深度的时候每条边都是为1来算),后面要用
  
  询问操作:
  1.输入每个询问的点,并且按照dfs序为关键字排序
  2.将第1个点压到栈当中,开始构建虚树
  3.枚举到下一个点u,计算u与栈顶点v的公共祖先lca
  4.假设栈中栈顶下方的点为w(若栈中只有1个点就直跳过这一步),若w点的深度大于lca就把v向w连一条边,并且弹掉v,重复此步,否则就到下一步
  5.若lca不是当前的v,那么就把lca和v连边,把v弹出,让lca成为栈顶元素(注:这个操作的意思是如果栈顶没有这个lca那么就压入),否则不做任何操作
  6.最后把u压入栈中
  7.回到3操作枚举下个点,直到枚举完了所有点
  8.把栈顶v与栈顶下方的点为w连边,并且把v弹掉,这么做直到栈里只有一个点
  9.栈里剩下的点就是虚树的根了
  接下来你就可以开始进行dp等操作了
  
  虚树的复杂度
  虚树的建树的复杂度是O(k∗log(n))的,树形dp就是O(k)的啦,因为考虑最后虚树上的关键点有询问的点,和lca,然后每个询问的点最多产生1个新的lca,所以复杂度就是对的啦
  
  来自https://blog.csdn.net/zhouyuheng2003/article/details/79110326
  大神的博客里写的很清楚了,具体看代码实现吧:)
  
  此题很容易发现用 dp 解决
  但是多组询问 \(O(nm)\) 会TLE
  重新建图把点缩少再跑 dp 就好了
  具体看代码实现吧:)


AC代码

#include <cstdio> 
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int N=250005;
const ll inf=5e10;
int n,Q,K,top,ind;
int a[N],h[N];
int cnt,_cnt,last[N],_last[N];
inline int read(){int x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x;
}
struct edge{int to,val,next;
}e[N<<1];
struct _edge{int to,next;
}_e[N];
void add_edge(int u,int v,int w){e[++cnt]=(edge){v,w,last[u]};last[u]=cnt;e[++cnt]=(edge){u,w,last[v]};last[v]=cnt;
}
void _add_edge(int u,int v){if(u==v)return;_e[++_cnt]=(_edge){v,_last[u]};_last[u]=_cnt;
}
int pos[N],dep[N],fa[N][20];
ll mn[N];
void dfs(int u){pos[u]=++ind;for(int i=last[u];i;i=e[i].next){int v=e[i].to;if(v==fa[u][0])continue;fa[v][0]=u;dep[v]=dep[u]+1;mn[v]=min(mn[u],(ll)e[i].val);dfs(v);}
}
int lca(int a,int b){if(dep[a]<dep[b])swap(a,b);for(int i=18;i>=0;i--)if(dep[fa[a][i]]>=dep[b])a=fa[a][i];for(int i=18;i>=0;i--)if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];if(a==b)return a;return fa[a][0];
}
bool cmp(int a,int b){return pos[a]<pos[b];
}
ll f[N];
void DP(int u){f[u]=mn[u];ll tmp=0;for(int i=_last[u];i;i=_e[i].next){int v=_e[i].to;DP(v);tmp+=f[v];}_last[u]=0;if(tmp!=0)f[u]=min(f[u],tmp);
}
int q[N];
void solve(){_cnt=0;K=read();for(int i=1;i<=K;i++)h[i]=read();sort(h+1,h+K+1,cmp);int tot=0;h[++tot]=h[1];for(int i=2;i<=K;i++)if(lca(h[tot],h[i])!=h[tot])h[++tot]=h[i];top=0;q[++top]=1;for(int i=1;i<=tot;i++){int now=h[i],F=lca(now,q[top]);while(1){if(dep[F]>=dep[q[top-1]]){_add_edge(F,q[top--]);if(q[top]!=F)q[++top]=F;break;}_add_edge(q[top-1],q[top]);top--;}if(q[top]!=now)q[++top]=now;}while(--top)_add_edge(q[top],q[top+1]);DP(1);printf("%lld\n",f[1]);
}
int main(){n=read();for(int i=1;i<n;i++){int u=read(),v=read(),w=read();add_edge(u,v,w);}mn[1]=inf;dep[1]=1;dfs(1);for(int j=1;j<=18;j++)for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];Q=read();while(Q--)solve();return 0;
}


  作者:skl_win
  出处:https://www.cnblogs.com/shaokele/
  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载于:https://www.cnblogs.com/shaokele/p/9507627.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/397155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java基础知识:Java实现Map集合二级联动4

comboBox.setModel(new DefaultComboBoxModel(getProvince())); // 添加省份信息 final JLabel label new JLabel(); label.setText("省/直辖市"); label.setBounds(155, 30, 66, 18); panel.add(label); final JLabel label_1 new JLabel(); label_1.setText(&quo…

linux QT 结束当前进程_Qt编写控件属性设计器7-串口采集

一、前言数据源是组态软件的核心灵魂&#xff0c;少了数据源&#xff0c;组态就是个花架子没卵用&#xff0c;一般数据源有三种方式获取&#xff0c;串口、网络、数据库&#xff0c;至于数据规则是什么&#xff0c;这个用户自己指定&#xff0c;本设计器全部采用第一个字节作为…

magento2邮件调试方法

order mail 直接打印到页面上 位置 vendor\magento\module-sales\Model\Order\Email\Sender.php Magento\Sales\Model\Order\Email\Sender::prepareTemplate() 添加代码 $objectManager \Magento\Framework\App\ObjectManager::getInstance(); $templateFactory $objectManag…

python多进程怎么样_Python执行多进程任务的方法

Python的多进程可以借助from multiprocessing import Pool来实现。简而言之分为这样几步&#xff1a;导入包from multiprocessing import Pool编写任务函数。def 任务函数(参数)实例化进程池并设置进程数。poolPool(欲设置的进程数)开始布置任务&#xff0c;把多个任务添加进多…

JAVA多线程之Synchronize 关键字原理

image众所周知 Synchronize 关键字是解决并发问题常用解决方案&#xff0c;有以下三种使用方式: 同步普通方法&#xff0c;锁的是当前对象。同步静态方法&#xff0c;锁的是当前 Class 对象。同步块&#xff0c;锁的是 {} 中的对象。实现原理&#xff1a;JVM 是通过进入、退出对…

iOS-数据持久化-第三方框架FMDB的使用

FMDB简单介绍 一、简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象&#xff0c;省去了很多麻烦、冗余的C语言代码 对比苹果自带的Core Data框架&#xff0c;更加轻量级和灵活 提供了多线程安全…

电脑word文档打不开怎么办_word怎么转pdf?两个值得学习的高效转换法

word怎么转pdf&#xff1f;两个值得学习的高效转换法word怎么转pdf&#xff1f;pdf格式是我们经常能够使用到的格式&#xff0c;因为pdf格式在传递的过程中能更好地避免文件出现乱码打不开或误触导致文件被修改的情况。那如果想要把word文件转换成pdf格式以避免阅读word时文件被…

sql server常用函数、常用语句

一、常用函数 1.字符串函数 &#xff1a; charindex(:,abc:123) --寻找一个字符在一段字符串中起始的位置 len(zhangsan) --获取一段字符串的长度 left(Ly,君子之耀,2) --从一段字符串左边返回指定长度的字符 right(char_expr,int_expr) --返回字符串右边int_expr个字符 …

python 矩阵乘法 跳过nan_python – Numpy:当一些向量元素等于零时,矩阵向量乘法不会跳过计算吗?...

我最近一直致力于一个项目,其中我的大部分时间花费在密集矩阵A和稀疏向量v上(见here).在我尝试减少计算时,我注意到A.dot(v)的运行时间不受v的零条目数的影响.为了解释为什么我希望在这种情况下改进运行时,让result A.dot.v使得j 1的结果[j] sum_i(A [i,j] * v [j])… v.sha…

[转]Responsive Tables Demo

本文转自&#xff1a;http://elvery.net/demo/responsive-tables/ A quick and dirty look at some techniques for designing responsive table layouts. This was put together in haste (and with the aid of Twitter Bootstrap) for What Do You Know Brisbane hosted by W…

Scala函数式对象-有理数

有理数类的表示 实现规范&#xff1a;支持有理数的加减乘除&#xff0c;并支持有理数的规范表示 1.定义Rational 首先&#xff0c;考虑用户如何使用这个类&#xff0c;我们已经决定使用“Immutable”方式来使用Rational对象&#xff0c;我们需要用户在定义Rational对象时提供分…

2020双十一实时大屏_2020拼多多双十一,拼多多双十一活动

2020拼多多双十一&#xff0c;拼多多双十一活动&#xff0c;2020拼多多双十一&#xff0c;拼多多双十一活动2020拼多多双十一&#xff0c;拼多多双十一活动拼多多双11来了全球狂欢节先领券再购物低价风暴 震撼来袭没有最低 只有更低拼多多优惠券商城拼多多优惠商城&#xff0c;…

dataTables本地刷新数据解决只能初始化一次问题

2019独角兽企业重金招聘Python工程师标准>>> dataTables的表格只能初始化一次&#xff0c;这样如果需要动态改变表格数据的话就需要写多个表格&#xff0c;这样很显然不是一个好的解决方案。 dataTables Api提供了刷新数据解决方案&#xff1a; 这里大概说一下案例&…

安装Ubuntu版本linux过程中没有提示设置root用户密码问题的解决办法

原来ubunto不提倡设置root用户&#xff0c;系统安装成功后&#xff0c;root密码是随机的&#xff0c;那么在这种情况下如何得到root权限呐&#xff0c;具体方法如下&#xff1a; 终端中输入&#xff1a;sudo passwd root 此时重新设置原登录用户的密码。 设置成功后在终端继续输…

linux命令headtail

一、head语法head [-n -k ]... [FILE]...//k是数字默认是显示开头前10行。head /etc/passwd显示开头前5行head -5 /etc/passwdhead -n 5 /etc/passwd&#xff08;注意和以下的有-的差别&#xff09;head -n 5 /etc/passwd 除最后k行外&#xff0c;显示剩余所有内容。head -n -5…

用-force –opengl 指令_苹果新系统ios14新功能汇总 轻点背面等小技巧怎么用

在 iOS 14 以及更新系统中&#xff0c;苹果为 iPhone X 以及更新机型带来了“轻点背面”功能&#xff0c;可以让用户轻点手机背面来实现更多操作&#xff0c;并且这项功能还支持“快捷指令”。例如&#xff0c;如果您不希望应用读取剪贴板中私密内容&#xff0c;可以利用“轻点…

PE文件格式(加密与解密3)(一)

本次的了解主要讲解 PE的基本概念、MS-DOS文件头、PE文件头、区块、输入表、输出表等。 这里我将会结合一个简单的小程序来加深我对PE文件结构的了解。 使用学习工具&#xff1a;有StudyPE、LordPE、PEID。 学习PE建议看书。。和自己动手。。。 PE文件&#xff1a; 在WIN上&…

mysql用户_MySQL用户权限管理详解

用户权限管理主要有以下作用&#xff1a;1. 可以限制用户访问哪些库、哪些表2. 可以限制用户对哪些表执行SELECT、CREATE、DELETE、DELETE、ALTER等操作3. 可以限制用户登录的IP或域名4. 可以限制用户自己的权限是否可以授权给别的用户一、用户授权mysql> grant all privile…

对ContentProvider中getType方法的一点理解

在上篇博客中我们介绍了自定义ContentProvider&#xff0c;但是遗漏掉了一个方法&#xff0c;那就是getType&#xff0c;自定义ContentProvider一般用不上getType方法&#xff0c;但我们还是一起来探究下这个方法究竟是干什么的&#xff1f;我们先来看看ContentProvider中对这个…

手把手教Electron+vue的使用

.现如今前端框架数不胜数&#xff0c;尤其是angular、vue吸引一大批前端开发者&#xff0c;在这个高新技术快速崛起的时代&#xff0c;自然少不了各种框架的结合使用。接下来是介绍electronvue的结合使用。 2.Electron是什么&#xff1f;&#xff1f; 对于我来说Electron相当于…