题面

虚树的模板题:

虚树的思想是只保留有用的点(在这道题目里面显然是标记点和lca),然后重新构建一棵树,从而使节点大大减少,优化复杂度

我们维护一条链(以1号点为根),这条链左边的所有在虚树上的位置都已经处理完毕;而这条链右边的和下面的都未处理;

这条链我们用栈来维护;

对于要新加的询问点now,对于虚树的影响有四种情况:(lc表示x与st[top]的LCA)

1.lc==st[top]      :  在虚树上连接st[top]与now

.

2.lc在st[top]与st[top-1]之间;在虚树上连接lc与st[top],--top,然后now进栈;

3.lc==st[top-1]    :--top,然后now进栈;

4.lc在st[top-1]之上 :在虚树上连接st[top-1]与st[top],然后退栈,重复以上步骤知道出现情况1、2、3;

在最后,我们把这条链加入到虚树中,这样一颗完美的虚树就建成了;

在每次建立虚树的时候,我们要实时清空虚树,否则时间复杂度会退化成O(n^2);

然后在这个虚树上跑dp,就可以了;

#include <bits/stdc++.h>
#define int long long
#define inc(i,a,b) for(register int i=a;i<=b;i++)
#define dec(i,a,b) for(register int i=a;i>=b;i--)
using namespace std;
int head1[500010],cnt1,head2[500010],cnt2;
class littlestar{
public:
int to,nxt;
long long w;
void add1(int u,int v,long long gg){
to=v; nxt=head1[u];
head1[u]=cnt1; w=gg;
}
void add2(int u,int v){
to=v; nxt=head2[u];
head2[u]=cnt2;
}
}star1[500010*2],star2[500010*2];
int n,f[500010][25],dfn[500010],cur,dep[500010];
long long minv[500010];
void dfs(int u)
{
inc(i,0,19){
f[u][i+1]=f[f[u][i]][i];
}
dfn[u]=++cur;
for(int i=head1[u];i;i=star1[i].nxt){
int v=star1[i].to;
if(!dfn[v]){
f[v][0]=u;
dep[v]=dep[u]+1;
minv[v]=min(minv[u],star1[i].w);
dfs(v);
}
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
dec(i,20,0){
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
}
if(x==y) return x;
dec(i,20,0){
if(f[x][i]!=f[y][i]){
x=f[x][i]; y=f[y][i];
}
}
return f[x][0];
}
bool cmp(int x,int y){return dfn[x]<dfn[y];}
int num;
int judge[500001],h[500010];
int st[500010],top;
int dp(int u)
{
long long summ=0;
for(int i=head2[u];i;i=star2[i].nxt){
int v=star2[i].to;
summ+=dp(v);
}
long long ans=0;
if(judge[u]) ans=minv[u];
else ans=min(minv[u],summ);
judge[u]=0;
head2[u]=0;
return ans;
}
signed main()
{
cin>>n;
inc(i,1,n-1){
int u,v; long long w;
scanf("%lld%lld%lld",&u,&v,&w);
star1[++cnt1].add1(u,v,w);
star1[++cnt1].add1(v,u,w);
}
minv[1]=1e17+21;
dfs(1);
int q; scanf("%lld",&q);
while(q--){
scanf("%lld",&num);
inc(i,1,num){
scanf("%lld",&h[i]);
judge[h[i]]=1;
}
sort(h+1,h+1+num,cmp);
top=1;
st[top]=h[1];
inc(i,2,num){
int LCA=lca(h[i],st[top]);
while(true){
if(dep[LCA]>=dep[st[top-1]]){
if(LCA!=st[top]){
star2[++cnt2].add2(LCA,st[top]);
if(LCA!=st[top-1]){
st[top]=LCA;
}
else{
--top;
}
}
else{
break;
}
}
else{
star2[++cnt2].add2(st[top-1],st[top]);
--top;
}
}
st[++top]=h[i];
}
while(--top){
star2[++cnt2].add2(st[top],st[top+1]);
}
cout<<dp(st[1])<<endl;
cnt2=0;
}
}

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

  1. BZOJ2286:[SDOI2011]消耗战——题解

    +++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...

  2. 【LG2495】[SDOI2011]消耗战

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

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

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

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

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

  5. 洛谷P2495 [SDOI2011]消耗战(虚树dp)

    P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...

  6. BZOJ 2286: [Sdoi2011]消耗战

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

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

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

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

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

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

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

随机推荐

  1. 如何使用PHP排序key为字母+数字的数组

    你还在为如何使用PHP排序字母+数字的数组而烦恼吗? 今天有个小伙伴在群里问: 如何将一个key为字母+数字的数组按升序排序呢? 举个例子: $test = [ 'n1' => 22423, ' ...

  2. Flask-配置参数

    Flask配置 Flask 是一个非常灵活且短小精干的web框架 , 那么灵活性从什么地方体现呢? 有一个神奇的东西叫 Flask配置 , 这个东西怎么用呢? 它能给我们带来怎么样的方便呢? 首先展示 ...

  3. 2016 Multi-University Training Contest 1 部分题解

    第一场多校,出了一题,,没有挂零还算欣慰. 1001,求最小生成树和,确定了最小生成树后任意两点间的距离的最小数学期望.当时就有点矛盾,为什么是求最小的数学期望以及为什么题目给了每条边都不相等的条件. ...

  4. Hdu 5248

    hdu5248-序列变换 题意: 给你一个序列A,要求改变序列A中的某些元素的顺序,形成一个新的数列B,并保证数列B严格单调递增,求出最小代价. 代价计算公式 $ cost(a,b)=max(|A_i ...

  5. CF883H

    CF883H 题意: 给你一个字符串,需要把它以最小的划分次数划分为x个长度相等的回文串,可以重新排列. 解法: 大模拟一个. 分别统计出现一次的字符和出现两次的字符,如果没有出现一次的字符,那么所有 ...

  6. 在docker 安装gitlab

    一.Centos 7 上安装 官方文档:https://docs.docker.com/install/linux/docker-ce/centos/ 1.安装环境      yum install  ...

  7. Leetcode题目101.对称二叉树(简单)

    题目描述: 给定一个二叉树,检查它是否是镜像对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的. 1 / \ 2 2 / \ / \ 3 4 4 3 但是下面这个 [1,2,2,null ...

  8. php 设置error_reporting(0)和ini_set('display_errors', 0)之后,还是显示错误

    php 5.4 apache 2.2 关闭错误报告和错误显示 依然会显示错误 按照我的理解,error_reporting(0)之后就应该不会显示错误了,这是怎么回事? 后来我又试着在php.ini者 ...

  9. set_multicycle_path语法说明【转载】

    (转载) (其实多看手册就知道原因了) Q:多周期路径中的检查保持时间时刻,为什么默认是在建立时间检查的前一个cycle?请大家谈谈自己的理解. 如:Set_multicycle_path -setu ...

  10. HashMap ArrayList 和 List对象的转换

    public static void main(String[] args) { List list = new ArrayList<>(); HashMap map = new Hash ...