在一场战争中,战场由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行,分别代表每次任务的最小代价。

题意:简单来说就是每次给k个点让1和给定点不能联通,求最小花费

解法:虚树,虚树就是把所有需要操作的点和他们的lca抠出来,然后直接在上面dp,保证每次抠出来的点不超过2k,

建树:先把需操作的点按dfs序排序,然后维护一个栈,表示从根到栈顶的链包含的需操作的点,

考虑栈顶元素是p,栈第二个元素是q,需插入的点是x,

如果lca(p,x)为p,代表x在p子树中,直接入栈即可,又lca(p,x)不可能为p(因为按dfs序插入的)

1.如果lca(p,x)的深度比q的深度小,那么链接栈顶和栈次顶,pop栈顶

2.如果lca(p,x)的深度比q的深度大或相同,那么链接lca和p,然后pop栈顶,lca入栈,x入栈(当lca(p,x)和q深度相同,那么不用加入lca,q就是lca)

最后把栈中元素全部出栈,并链接

最后在虚树上dp,如果当前点要被ban,那么肯定删上面的一条边,否则选上面的边和下面的dp之和中小的

(虚树题目很明显,多次查询,每次选取一些点操作,总的点不会很大,那么就可以用虚树)

/**************************************************************
Problem: 2286
User: walfy
Language: C++
Result: Accepted
Time:12852 ms
Memory:61228 kb
****************************************************************/ //#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6;
const int N=250000+10,maxn=500000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; vector<pair<int,int> >v[N];
vi in;
struct edge{
int to,Next,c;
}e[maxn];
int cnt,head[N],deep[N];
int fa[20][N],mi[20][N],l[N],res;
void init()
{
cnt=res=0;
memset(head,-1,sizeof head);
memset(mi,inf,sizeof mi);
}
void add(int u,int v,int c)
{
e[cnt].to=v;
e[cnt].c=c;
e[cnt].Next=head[u];
head[u]=cnt++;
}
void dfs(int u,int f,int dep)
{
l[u]=++res;
deep[u]=dep;
for(int i=head[u];~i;i=e[i].Next)
{
int x=e[i].to;
if(x!=f)
{
fa[0][x]=u;mi[0][x]=e[i].c;
dfs(x,u,dep+1);
}
}
}
void gao(int n)
{
for(int i=1;i<20;i++)
{
for(int j=1;j<=n;j++)
{
fa[i][j]=fa[i-1][fa[i-1][j]];
mi[i][j]=min(mi[i-1][fa[i-1][j]],mi[i-1][j]);
}
}
}
int lca(int x,int y)
{
if(deep[x]>deep[y])swap(x,y);
for(int i=19;i>=0;i--)
if(((deep[y]-deep[x])>>i)&1)
y=fa[i][y];
if(x==y)return x;
for(int i=19;i>=0;i--)
{
if(fa[i][x]!=fa[i][y])
{
x=fa[i][x];
y=fa[i][y];
}
}
return fa[0][x];
}
int getmi(int a,int b)
{
if(deep[a]>deep[b])swap(a,b);
int ans=inf;
for(int i=19;i>=0;i--)
{
if(deep[fa[i][b]]>deep[a])
{
ans=min(ans,mi[i][b]);
b=fa[i][b];
}
}
return min(ans,mi[0][b]);
}
void add1(int a,int b,int c){v[a].pb(mp(b,c));in.pb(a);in.pb(b);}
int st[N],top,a[N];
ll dp[N];
void ins(int x)
{
if(!top){st[++top]=x;return ;}
int lc=lca(st[top],x);
while(top>1&&deep[st[top-1]]>deep[lc])
add1(st[top-1],st[top],getmi(st[top-1],st[top])),top--;
if(top>=1&&deep[st[top]]>deep[lc])
add1(lc,st[top],getmi(st[top],lc)),top--;
if(!top||deep[st[top]]<deep[lc])st[++top]=lc;
st[++top]=x;
}
bool cmp(int a,int b){return l[a]<l[b];}
bool ban[N];
void dfs1(int u,ll mm)
{
for(int i=0;i<v[u].size();i++)
dfs1(v[u][i].fi,v[u][i].se);
if(ban[u]){dp[u]=mm;return ;}
else
{
ll res=0;
for(int i=0;i<v[u].size();i++)
res+=dp[v[u][i].fi];
dp[u]=min(res,mm);
}
}
int main()
{
int n;
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);add(b,a,c);
}
dfs(1,-1,1);gao(n);
int m;scanf("%d",&m);
for(int i=1;i<=m;i++)
{
in.clear();
int k;
scanf("%d",&k);
for(int j=0;j<k;j++)scanf("%d",&a[j]),ban[a[j]]=1;
sort(a,a+k,cmp);
top=0;ins(1);
for(int j=0;j<k;j++)ins(a[j]);
while(top>=2)add1(st[top-1],st[top],getmi(st[top-1],st[top])),top--;
dfs1(1,1e18);
printf("%lld\n",dp[1]);
for(int j=0;j<in.size();j++)
v[in[j]].clear(),dp[in[j]]=0,ban[in[j]]=0;
}
return 0;
}
/********************
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
1000
2 10 6
4 5 7 8 3
3 9 4 6
********************/

bzoj2286: [Sdoi2011]消耗战 虚树的更多相关文章

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

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

  2. BZOJ2286: [Sdoi2011]消耗战(虚树/树形DP)

    Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5246  Solved: 1978[Submit][Status][Discuss] Descript ...

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

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

  4. 【BZOJ-2286】消耗战 虚树 + 树形DP

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

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

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

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

    题目大意:多次给出关键点,求切断边使所有关键点与1断开的最小费用 分析:每次造出虚树,dp[i]表示将i和i子树与父亲断开费用 对于父亲x,儿子y ①y为关键点:\(dp[x]\)+=\(dismn( ...

  7. 【BZOJ】2286: [Sdoi2011]消耗战 虚树+DP

    [题意]给定n个点的带边权树,每次询问给定ki个特殊点,求隔离点1和特殊点的最小代价.n<=250000,Σki<=500000. [算法]虚树+DP [题解]考虑普通树上的dp,设f[x ...

  8. [SDOI2011]消耗战(虚树+树形动规)

    虚树dp 虚树的主要思想: 不遍历没用的的节点以及没用的子树,从而使复杂度降低到\(\sum\limits k\)(k为询问的节点的总数). 所以怎么办: 只把询问节点和其LCA放入询问的数组中. 1 ...

  9. bzoj 2286(洛谷 2495) [Sdoi2011]消耗战——虚树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2286 https://www.luogu.org/problemnew/show/P2495 ...

随机推荐

  1. SaltStack安装及配置

    1.简介SaltStack是一个服务器基础架构集中化管理平台,具备配置管理.远程执行.监控等功能,一般可以理解为简化版的puppet和加强版的func.SaltStack基于Python语言实现,结合 ...

  2. vue v-for 和 v-if 、v-else一起使用造成的bug

    现象:导致v-else 执行v-for的length次数, 从现象看应该v-for先解析,然后将v-if和v-else包在其中 解决方案:很简单,tempalte 将v-if v-else 隔离到最外 ...

  3. Web负载均衡学习笔记之四层和七层负载均衡的区别

    0x00 简介 简单理解四层和七层负载均衡: ① 所谓四层就是基于IP+端口的负载均衡:七层就是基于URL等应用层信息的负载均衡:同理,还有基于MAC地址的二层负载均衡和基于IP地址的三层负载均衡. ...

  4. bzoj1689 / P1589 [Usaco2005 Open] Muddy roads 泥泞的路

    P1589 [Usaco2005 Open] Muddy roads 泥泞的路 简单的模拟题. 给水坑排个序,蓝后贪心放板子. 注意边界细节. #include<iostream> #in ...

  5. linux内核分析 第三周

    一.Linux内核源码(简单分析) README 一开始刚接触内核源码的时候,不知道代码文件是什么功能.不清楚如何使用文件的时候,就需要打开README. README提供了内核的各种编译方法.生成文 ...

  6. [c/c++]指针(4)

    现在讲一下指针的主要用途和常见错误. [用途] 1.用作形参 首先,常见新手写交换函数: void swap(int a,int b){ int t = a; a = b; b = t; } 主函数里 ...

  7. BZOJ 2434 阿狸的打字机(fail树)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2434 题意:阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28 ...

  8. 【概念、概述】Spark入门教程[1]

    本教程源于2016年3月出版书籍<Spark原理.机制及应用> ,如有兴趣,请支持正版书籍. 随着互联网为代表的信息技术深度发展,其背后由于历史积累产生了TB.PB甚至EB级数据量,由于传 ...

  9. rg.apache.ibatis.binding.BindingException: Mapper method 'com.dao.Cameao.getOnlineDayRation attempted to return null from a method with a primitive return type (float)

    本文为博主原创,未经允许不得转载: 异常展示如下: org.apache.ibatis.binding.BindingException: Mapper method 'com.dao.Cameao. ...

  10. LA 3027 合作网络

    https://vjudge.net/problem/UVALive-3027 题意: 有n个结点,初始时每个结点的父节点都不存在.你的任务是执行一次I操作和E操作,格式如下: I u v:把结点u的 ...