虚树的核心就是把关键点和关键点的lca重新生成一棵树,然后在这棵树上进行dp

https://www.cnblogs.com/zwfymqz/p/9175152.html  写的很好的博客

建立虚树的核心代码

void insert(int x){
if(top==){stk[++top]=x;return;}
int lca=LCA(x,stk[top]);
if(lca==stk[top])return;//这里本来要stk[++top]=x的,但是由于本题特殊性,所以删去优化时间
while(top> && dfn[lca]<=dfn[stk[top-]])
add_edge(stk[top-],stk[top]),--top;
if(lca!=stk[top])//如果lca不是关键点,把它做成关键点,即把lca和栈顶元素连边,然后栈顶元素出栈,lca进栈
add_edge(lca,stk[top]),stk[top]=lca;
stk[++top]=x;
}

本题的ac代码

#include<bits/stdc++.h>
using namespace std;
#define maxn 250005
#define ll long long
struct Edge{int to,nxt,w;}e[maxn<<];
int head[maxn],tot;
void add(int u,int v,int w){
e[tot].nxt=head[u];e[tot].to=v;e[tot].w=w;head[u]=tot++;
}
//树链剖分
ll Min[maxn];
int fa[maxn],son[maxn],topf[maxn],size[maxn],d[maxn],dfn[maxn],ind;
void dfs1(int u,int pre){
fa[u]=pre;size[u]=;
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==pre)continue;
d[v]=d[u]+;
Min[v]=min(Min[u],(ll)e[i].w);
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
topf[u]=tp;dfn[u]=++ind;
if(!son[u])return;
dfs2(son[u],tp);
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(!topf[v])
dfs2(v,v);
}
}
//求lca
int LCA(int x,int y){
while(topf[x]!=topf[y]){
if(d[topf[x]]<d[topf[y]])
swap(x,y);
x=fa[topf[x]];
}
if(d[x]>d[y])swap(x,y);
return x;
}
//建立虚树 int top,stk[maxn];
vector<int>G[maxn];
void add_edge(int u,int v){G[u].push_back(v);} void insert(int x){
if(top==){stk[++top]=x;return;}
int lca=LCA(x,stk[top]);
if(lca==stk[top])return;
while(top> && dfn[lca]<=dfn[stk[top-]])//把lca以下的关键点都入栈
add_edge(stk[top-],stk[top]),--top;
if(lca!=stk[top])//如果lca不是关键点,把它做成关键点
add_edge(lca,stk[top]),stk[top]=lca;
stk[++top]=x;
}
//在虚树上dp
ll dfs3(int u){
if(G[u].size()==)return Min[u];
ll res=;
for(int i=;i<G[u].size();i++)
res+=dfs3(G[u][i]);
G[u].clear();
return min(res,Min[u]);
} int cmp(int a,int b){return dfn[a]<dfn[b];} int n,m,x,y,z,a[maxn]; int main(){
memset(head,-,sizeof head);
Min[]=1ll<<;
cin>>n;
for(int i=;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
d[]=;
dfs1(,),dfs2(,); cin>>m;
while(m--){
int k;scanf("%d",&k);
for(int i=;i<=k;i++)scanf("%d",&a[i]);
sort(a+,a++k,cmp);
top=;
stk[top]=;G[].clear(); for(int i=;i<=k;i++)insert(a[i]);
while(top)
add_edge(stk[top-],stk[top]),top--; //进行dp
cout<<dfs3()<<endl;
}
return ;
}

虚树(树形dp套路)模板——bzoj2286的更多相关文章

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

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

  2. bzoj 2286(虚树+树形dp) 虚树模板

    树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5002  Sol ...

  3. 【BZOJ-3572】世界树 虚树 + 树形DP

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1084  Solved: 611[Submit][Status ...

  4. BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca

    BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...

  5. BZOJ5341[Ctsc2018]暴力写挂——边分治+虚树+树形DP

    题目链接: CSTC2018暴力写挂 题目大意:给出n个点结构不同的两棵树,边有边权(有负权边及0边),要求找到一个点对(a,b)满足dep(a)+dep(b)-dep(lca)-dep'(lca)最 ...

  6. [WC2018]通道——边分治+虚树+树形DP

    题目链接: [WC2018]通道 题目大意:给出三棵n个节点结构不同的树,边有边权,要求找出一个点对(a,b)使三棵树上这两点的路径权值和最大,一条路径权值为路径上所有边的边权和. 我们按照部分分逐个 ...

  7. 2018.09.25 bzoj3572: [Hnoi2014]世界树(虚树+树形dp)

    传送门 虚树入门题? 好难啊. 在学习别人的写法之后终于过了. 这道题dp方程很好想. 主要是不好写. 简要说说思路吧. 显然最优值只能够从子树和父亲转移过来. 于是我们先dfs一遍用儿子更新父亲,然 ...

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

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

  9. 【BZOJ2286】【SDOI2011】消耗战 [虚树][树形DP]

    消耗战 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一场战争中,战场由n个岛屿和n-1 ...

  10. 2018.09.25 bzoj2286: [Sdoi2011]消耗战(虚树+树形dp)

    传送门 又一道虚树入门题. 这个dp更简单啊. 直接记录每个点到1的距离,简单转移就行了. 代码: #include<bits/stdc++.h> #define N 250005 #de ...

随机推荐

  1. js 实现弹出层效果

    代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <tit ...

  2. git命令的基本使用

    git init 创建仓库 git status  查看当前版本库的状态 git add filename    使用git add命令告诉git,把该文件添加到仓库 git commit -m 'c ...

  3. Jmeter-【JSON Extractor】-响应结果中数组多个相同key取值

    一.请求返回样式 二.取所有option的值 三.查看结果

  4. sql update语句

    如果要更新数据库表中的记录,我们就必须使用UPDATE语句. UPDATE语句的基本语法是: UPDATE <表名> SET 字段1=值1, 字段2=值2, ... WHERE ...; ...

  5. apue.h报错问题

    下载apue.3e后进入make,提示错误如下: collect2: error: exit status Makefile:: recipe for target 'badexit2' failed ...

  6. Tyvj 1518 CPU监控(线段树)

    题目描述: Bob需要一个程序来监视CPU使用率.这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事. Bob会干很多事,除了跑暴力程序看视频之外,还会做出去玩玩和用 ...

  7. 性能超过DRUID的最强数据库连接池——HikariCP相关配置及简单示例

    在配置application.yml时,对hikari的配置会有这样一个字段validationQuery. validationQuery是用来验证数据库连接的查询语句,这个查询语句必须是至少返回一 ...

  8. cartographer和ROS的坐标系关系

    参考定义见:backpack_3d.lua    Local map frame是一次slam过程中的原点.但是现在cartographer支持Incremental mapping.global m ...

  9. delphi 多线程编程

    开始本应该是一篇洋洋洒洒的文字, 不过我还是提倡先做起来, 在尝试中去理解.先试试这个: procedure TForm1.Button1Click(Sender: TObject); var i: ...

  10. ArcGIS version not specified.

    问题 在调用arcgis10 的ISurface用来取指定航线的地形时,这段代码在加载.dem时总是出错. 报: Fail to open raster dataset 解决方法: 在窗体中加载Map ...