题目描述

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

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

输入输出格式

输入格式:

第一行一个整数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,表示资源丰富岛屿的编号。

输出格式:

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

输入输出样例

输入样例#1: 复制

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
输出样例#1: 复制

12
32
22

说明

【数据规模和约定】

对于10%的数据,2<=n<=10,1<=m<=5,1<=ki<=n-1

对于20%的数据,2<=n<=100,1<=m<=100,1<=ki<=min(10,n-1)

对于40%的数据,2<=n<=1000,m>=1,sigma(ki)<=500000,1<=ki<=min(15,n-1)

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

如果是单次询问,可以$O(n)$的树dp做出来

这题询问数很多,但$k$的和不大

对于每次询问,我们建一棵“虚树”

这棵虚树只包括询问点以及相应的lca

这样在虚树上dp复杂度为$O(k)$

总复杂度为$O(\sumk)$

树dp可以这样Min[x]表示1~x路径上最小的边

f[x]表示1无法到达x子树中关键点的最小和

f[x]=min(Min[x],∑f[v])

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long lol;
const int N=;
struct Node
{
int next,to;
lol dis;
}edge[N],edge2[N];
int head[N],head2[N],num,dep[N],a[N],s[N],cnt,dfn[N];
int fa[N][],vis[N],n,top,bin[],ed[N],M;
lol Min[N];
int gi()
{
char ch=getchar();
int x=;
while (ch<''||ch>'') ch=getchar();
while (ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x;
}
bool cmp(int a,int b)
{
return dfn[a]<dfn[b];
}
void add(int u,int v,lol w)
{
num++;
edge[num].next=head[u];
head[u]=num;
edge[num].to=v;
edge[num].dis=w;
}
void dfs(int x,int pa)
{int i;
dep[x]=dep[pa]+;
dfn[x]=++cnt;
for (i=;bin[i]<=dep[x];i++)
fa[x][i]=fa[fa[x][i-]][i-];
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (v==pa) continue;
Min[v]=min(Min[x],edge[i].dis);
fa[v][]=x;
dfs(v,x);
}
ed[x]=cnt;
}
int lca(int x,int y)
{int as,i;
if (dep[x]<dep[y]) swap(x,y);
for (i=;i>=;i--)
if (bin[i]<=dep[x]-dep[y])
x=fa[x][i];
if (x==y) return x;
for (i=;i>=;i--)
{
if (fa[x][i]!=fa[y][i])
{
x=fa[x][i];y=fa[y][i];
}
}
return fa[x][];
}
void add2(int u,int v)
{
if (u==v) return;
num++;
edge2[num].next=head2[u];
head2[u]=num;
edge2[num].to=v;
}
lol dp(int x)
{int i;
if (vis[x])
return Min[x];
lol tmp=;
for (i=head2[x];i;i=edge2[i].next)
{
int v=edge2[i].to;
tmp+=dp(v);
}
head2[x]=;
return min(tmp,Min[x]);
}
int main()
{int i,u,v,j,q,k;
lol w;
cin>>n;
bin[]=;
for (i=;i<=;i++)
bin[i]=bin[i-]*;
for (i=;i<=n-;i++)
{
scanf("%d%d%lld",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
Min[]=2e15;
dfs(,);
cin>>q;
while (q--)
{
k=gi();
M=k;
num=;
for (i=;i<=k;i++)
a[i]=gi(),vis[a[i]]=;
sort(a+,a+k+,cmp);
for (i=;i<=k;i++)
if (ed[a[i-]]<dfn[a[i]])
a[++M]=lca(a[i-],a[i]);a[++M]=;
sort(a+,a+M+,cmp);
M=unique(a+,a+M+)-a-;
s[++top]=a[];
for (i=;i<=M;i++)
{
while (top&&ed[s[top]]<dfn[a[i]]) top--;
add2(s[top],a[i]);
s[++top]=a[i];
}
printf("%lld\n",dp());
for (i=;i<=M;i++)
vis[a[i]]=head2[a[i]]=;
}
}

[SDOI2011]消耗战的更多相关文章

  1. BZOJ 2286: [Sdoi2011]消耗战

    2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2082  Solved: 736[Submit][Status] ...

  2. bzoj 2286: [Sdoi2011]消耗战 虚树+树dp

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一 ...

  3. bzoj千题计划254:bzoj2286: [Sdoi2011]消耗战

    http://www.lydsy.com/JudgeOnline/problem.php?id=2286 虚树上树形DP #include<cmath> #include<cstdi ...

  4. 【LG2495】[SDOI2011]消耗战

    [LG2495][SDOI2011]消耗战 题面 洛谷 题解 参考博客 题意 给你\(n\)个点的一棵树 \(m\)个询问,每个询问给出\(k\)个点 求将这\(k\)个点与\(1\)号点断掉的最小代 ...

  5. AC日记——[SDOI2011]消耗战 洛谷 P2495

    [SDOI2011]消耗战 思路: 建虚树走树形dp: 代码: #include <bits/stdc++.h> using namespace std; #define INF 1e17 ...

  6. [BZOJ2286][SDOI2011]消耗战(虚树DP)

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4998  Solved: 1867[Submit][Statu ...

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

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

  8. 【BZOJ2286】[Sdoi2011]消耗战 虚树

    [BZOJ2286][Sdoi2011]消耗战 Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的 ...

  9. 2286: [Sdoi2011]消耗战

    2286: [Sdoi2011]消耗战 链接 分析 虚树练习题. 构建虚树,在虚树上DP. 跟着gxb学虚-tree... 代码 #include <cstdio> #include &l ...

  10. BZOJ2286 [Sdoi2011]消耗战 和 BZOJ3611 [Heoi2014]大工程

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6371  Solved: 2496[Submit][Statu ...

随机推荐

  1. beta冲刺6

    前言:此篇是补昨天凌晨的.后面有更新但是太晚了就没有即使更新.所以现在过来更新一下. 昨天的未完成: 用户测试+测试报告 目前剩下的功能点:输入内容检测 我的社团输出显示格式调整. 今天的完成: 我的 ...

  2. 网络1712--c语言第一次作业总结

    1.作业亮点 1.1大家均能较为独立自主地完成第一次c语言作业,无明显抄袭现象 1.2 以下几位同学博文写的较为优秀,可作为范例供大家参考 田亚琴--态度端正,及时回复评论并及时完善修改博文 戴洁-- ...

  3. 2017-2018-1 20155215 第五周 mybash的实现

    题目要求 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解,实现过程和问题解决的博客(包含代码托管链接) 学习fork,exec,wait fork ma ...

  4. 2017-2018-1 20155306 mypwd的实现

    2017-2018-1 20155306 mypwd的实现 一.pwd的使用 功能: Linux中用 pwd 命令来查看"当前工作目录"的完整路径. 命令格式:pwd [选项] 命 ...

  5. alpha-咸鱼冲刺day7

    一,合照 emmmmm.自然还是没有的. 二,项目燃尽图 三,项目进展 正在写登陆+注册ing 注册搞出来了!!!!!!!!QAQ(喜极而泣!!!!.jpg) 四,问题困难 数据流程大概是搞定了.不过 ...

  6. zookeeper 启动失败 BindException: Address already in use 或者Error contacting service. It is probably not running

    平台:centos-6.3-i386 jdk-7u51 storm 0.9.1 python 2.6.6   hadoop 1.2.1 今天上午装storm的时候遇到这个问题,好郁闷.把网上介绍的方法 ...

  7. L2 约束的最小二乘学习法

    \[ \begin{align*} &J_{LS}{(\theta)} = \frac { 1 }{ 2 } { \left\| \Phi \theta - y \right\| }^{ 2 ...

  8. 快速获取表单多条数据,使用ajax传递给后台

    当表单中有多条数据需要向后台传递时,一个一个的获取显然是不可取的办法,可以借助表单的serialize()方法获取. HTML: <form id="form"> &l ...

  9. JS字符串和数组常用方法

    1.indexOf() – 返回字符串中一个字符第一处出现的索引,接收2个参数:要查找的字符,从哪个位置开始查找:.lastIndexOf()--返回字符串中某一个字符最后一次出现的索引值. 如果没有 ...

  10. 【微信小程序】对微信http请求API的封装,方便对错误码进行处理

    /**   * App 微信配置文件app.js   * author: nujey   * versions: 1.0.0   */   App({   /**   * @param {Object ...