题目

【题目描述】

在一场战争中,战场由 $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

代码

 #include<bits/stdc++.h>
#define LL long long
#define pb push_back
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
int R(){
int x;bool f=;char ch;_(!)if(ch=='-')f=;x=ch^;
_()x=(x<<)+(x<<)+(ch^);return f?x:-x;}
const int N=2.5e5+;
int n,m,f[N][],head[N],cnt,dfn[N],dep[N],a[N],sta[N],top,tot,lg;
LL g[N];
vector<int>G[N];
struct edge{int to,nex;LL w;}e[N<<];
bool cmp(int a,int b){return dfn[a]<dfn[b];}
void add(int s,int t,int w){e[++cnt]=(edge){t,head[s],w},head[s]=cnt;}
void dfs(int u,int far){
dfn[u]=++tot,f[u][]=far,dep[u]=dep[far]+;
for(int i=;i<=lg;i++)f[u][i]=f[f[u][i-]][i-];
for(int k=head[u],v;k;k=e[k].nex)
if((v=e[k].to)!=far)
g[v]=min(g[u],e[k].w),dfs(v,u);
}
int lca(int x,int y){
if(dep[x]>dep[y])swap(x,y);
int i=lg;
while(dep[x]<dep[y]){
while(i&&dep[x]>dep[f[y][i]])i--;
y=f[y][i];}
i=lg;
while(x!=y){
while(i>&&f[x][i]==f[y][i])i--;
x=f[x][i],y=f[y][i];}
return x;
}
void insert(int x){
if(top==){sta[++top]=x;return;}
int far=lca(x,sta[top]);
if(far==sta[top])return;
while(top>&&dfn[sta[top-]]>=dfn[far])
G[sta[top-]].pb(sta[top]),top--;
if(far!=sta[top])G[far].pb(sta[top]),sta[top]=far;
sta[++top]=x;
return;
}
LL work(int x){
if(!G[x].size())return g[x];
LL sum=;
for(int i=G[x].size()-;~i;i--)
sum+=work(G[x][i]);
G[x].clear();
return min(sum,(LL)g[x]);
}
int main(){
memset(g,0x3f,sizeof g);
n=R(),lg=log2(n)+;
for(int i=,u,v,w;i<n;i++)
u=R(),v=R(),w=R(),add(u,v,w),add(v,u,w);
dfs(,);
for(int q=R();q--;){
m=R();
for(int i=;i<=m;i++)a[i]=R();
sort(a+,a++m,cmp);
sta[top=]=;
for(int i=;i<=m;i++)insert(a[i]);
while(top)G[sta[top-]].pb(sta[top]),top--;
printf("%lld\n",work());
}
return ;
}

最新文章

  1. lintcode二叉树的锯齿形层次遍历 (双端队列)
  2. win7下利用VM8安装CentOS6.3配置静态IP上网
  3. SQLite的优化总结
  4. Table的行列合并
  5. c :set标签的陷阱(未解决)
  6. OAF_文件系列9_实现OAF解析Excel并读取至数据库JXL
  7. js多文件上传
  8. jquery stop( ) 的用法 (转)
  9. ansible 2.2的源码编译安装
  10. [芯片][MPU6050] MPU60X0的DMP相关链接
  11. 侧滑SilidingMenu ,ViewPager 和,PagerIndicator 冲突
  12. Gulp 总结
  13. ArcGIS 10.1 for Desktop新特性之地理标记照片
  14. SQL连接方式(内连接,外连接,交叉连接)
  15. 解决Nginx的connect() to 127.0.0.1:8080 failed (13: Permission denied) while connect
  16. 全新安装免费的OS X Mavericks 10.9正式版--安装U盘制作指南
  17. html5 安卓拨打电话 发短信
  18. cookie跟session自我介绍
  19. 文末福利丨i春秋互联网安全校园行第1站精彩回顾
  20. Java中List集合去除重复数据的方法

热门文章

  1. 如何更好的理解js中的this,分享2段有意思的代码
  2. utc时间、本地时间及时间戳转化
  3. 利用Perlin nosie 完成(PS 滤镜—— 分成云彩)
  4. json 文件解析与应用
  5. 用Fiddler2来监听HTTP(记:用skydrive sdk访问时,出错后用Fidder抓包分析)
  6. JavaScript-Tool:template
  7. 集群重启某一主机下所有osd down解决办法
  8. pycharm安装 package报错:module &#39;pip&#39; has no attribute &#39;main&#39;
  9. 基于ftp服务实现yum网络共享
  10. [51nod1272]最大距离(贪心)