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

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#define N (250009)
#define LL long long
using namespace std; struct Edge{int to,next,len;}edge[N<<];
int n,m,k,u,v,l,dfs_num;
int a[N],Depth[N],f[N][],DFN[N];
LL Min[N];
int head[N],num_edge; void add(int u,int v,int l)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
edge[num_edge].len=l;
head[u]=num_edge;
} void DFS(int x,int fa)
{
f[x][]=fa;
for (int i=; i<=; ++i) f[x][i]=f[f[x][i-]][i-];
DFN[x]=++dfs_num; Depth[x]=Depth[fa]+;
for (int i=head[x]; i; i=edge[i].next)
if (edge[i].to!=fa)
{
Min[edge[i].to]=min(Min[x],(LL)edge[i].len);
DFS(edge[i].to,x);
}
} int LCA(int x,int y)
{
if (Depth[x]<Depth[y]) swap(x,y);
for (int i=; i>=; --i)
if (Depth[f[x][i]]>=Depth[y]) x=f[x][i];
if (x==y) return x;
for (int i=; i>=; --i)
if (f[x][i]!=f[y][i]) x=f[x][i], y=f[y][i];
return f[x][];
} vector<int>E[N];
void ADD(int x,int y) {E[x].push_back(y);}
int stack[N],top;
bool cmp(int x,int y) {return DFN[x]<DFN[y];} void Insert(int x)
{
if (top==) {stack[++top]=x; return;}
int lca=LCA(x,stack[top]);
if (lca==stack[top]) return;
// if (lca==stack[top]) {stack[++top]=x; return;}
while (top> && DFN[stack[top-]]>=DFN[lca])
ADD(stack[top-],stack[top]), top--;
if (lca!=stack[top]) ADD(lca,stack[top]), stack[top]=lca;
stack[++top]=x;
} void Build()
{
stack[top=]=;
for (int i=; i<=k; ++i) Insert(a[i]);
while (top>=) ADD(stack[top-],stack[top]), top--;
} LL DP(int x)
{
int sz=E[x].size();
if (!sz) return Min[x];
LL ans=;
for (int i=; i<sz; ++i)
ans+=DP(E[x][i]);
E[x].clear();
return min(ans,Min[x]);
} int main()
{
Min[]=1e18;
scanf("%d",&n);
for (int i=; i<=n-; ++i)
{
scanf("%d%d%d",&u,&v,&l);
add(u,v,l); add(v,u,l);
}
DFS(,);
scanf("%d",&m);
for (int i=; i<=m; ++i)
{
scanf("%d",&k);
for (int j=; j<=k; ++j) scanf("%d",&a[j]);
sort(a+,a+k+,cmp);
Build();
printf("%lld\n",DP());
}
}

BZOJ2286:[SDOI2011]消耗战(树形DP,虚树)的更多相关文章

  1. [luoguP2495] [SDOI2011]消耗战(DP + 虚树)

    传送门 明显虚树. 别的题解里都是这样说的. 先不考虑虚树,假设只有一组询问,该如何dp? f[u]表示把子树u中所有的有资源的节点都切掉的最优解 如果节点u需要切掉了话,$f[u]=val[u]$ ...

  2. P2495 [SDOI2011]消耗战 lca倍增+虚树+树形dp

    题目:给出n个点的树  q次询问  问切断 k个点(不和1号点联通)的最小代价是多少 思路:树形dp  sum[i]表示切断i的子树中需要切断的点的最小代价是多少 mi[i]表示1--i中的最小边权 ...

  3. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  4. 【CF809E】Surprise me! 树形DP 虚树 数学

    题目大意 给你一棵\(n\)个点的树,每个点有权值\(a_i\),\(a\)为一个排列,求 \[ \frac{1}{n(n-1)}\sum_{i=1}^n\sum_{j=1}^n \varphi(a_ ...

  5. 3611: [Heoi2014]大project|树形DP|虚树

    构建出虚树然后DP统计答案 自己写的DP太傻QAQ,各种WA 膜了一发PoPoQQQ大爷的DP方法 mxdis,mndis分别表示到当前点近期和最远的被选出来的点的距离 mx,mn分别表示在以当前点为 ...

  6. CF613D:Kingdom and its Cities(树形DP,虚树)

    Description 一个王国有n座城市,城市之间由n-1条道路相连,形成一个树结构,国王决定将一些城市设为重要城市. 这个国家有的时候会遭受外敌入侵,重要城市由于加强了防护,一定不会被占领.而非重 ...

  7. BZOJ3611:[HEOI2014]大工程(树形DP,虚树)

    Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道.  我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上.  在 2 个国家 a,b 之间建一条新通 ...

  8. 【BZOJ-1040】骑士 树形DP + 环套树 + DFS

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3312  Solved: 1269[Submit][Status ...

  9. HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...

随机推荐

  1. 微信小程序开发总结(详细)

    转载: 小程序开发总结(详细) 这段时间一直在做小程序,总结下.后续可能会不断更新,努力写仔细点,争取让人看到就能会写. 一,页面结构. 这基本是小程序的标准目录结构.我们从上到下解释下:pages文 ...

  2. 二:Servlet

    一:servlet开端 1.servlet是什么? a.就是一个java类 b.服务器端的小程序 c.处理用户请求 2.servlet的实现: a.实现Servlet接口 b.继承GenericSer ...

  3. IntelliJ IDEA创建spring-boot项目

    开发环境: jdk版本:JDK8 maven版本:maven-3.5.2 开发工具:Itellij IDEA 2017.1 前提条件:已安装以上软件并配置好jdk和maven的环境变量 创建步骤: 点 ...

  4. [js高手之路]Node.js模板引擎教程-jade速学与实战1-基本用法

    环境准备: 全局安装jade: npm install jade -g 初始化项目package.json: npm init --yes 安装完成之后,可以使用 jade --help 查看jade ...

  5. vue-router 路由懒加载

    webpack打包会将所有资源文件合并压缩成一个文件,导致最终的文件非常大,甚至超过几M,以致页面首次加载会比较慢,如下图: 其中红色标出的是在浏览器中加载的js文件,gzip压缩前已经达到500多K ...

  6. js-权威指南学习笔记15.3

    1.如果要明确地选取一个表单元素,可以索引表单对象的elements属性:document.forms.address.elements.street--一个name为address的form下的na ...

  7. 转:PHP中的使用curl发送请求(GET请求和POST请求)

    原文地址:http://www.jb51.net/article/104974.htm 使用CURL发送请求的基本流程 使用CURL的PHP扩展完成一个HTTP请求的发送一般有以下几个步骤: 1.初始 ...

  8. hadoop HA集群搭建步骤

      NameNode DataNode Zookeeper ZKFC JournalNode ResourceManager NodeManager node1 √   √ √   √   node2 ...

  9. RecyclerView中notifyDataSetChanged刷新总结

    除了adapter.notifyDataSetChanged()这个方法之外,新的Adapter还提供了其他的方法,如下: public final void notifyDataSetChanged ...

  10. 树莓派发射FM波——搭建私人小电台

    树莓派的应用十分广泛,有很多奇思妙想的应用非常有趣,在这里我们想实现一个小电台的功能,但是在这里需要说明,私人架设电台是违法行为,所以本案只作为自我娱乐所用,不能发射大功率的信号干扰正常的FM频段. ...