虚树(树形dp套路)模板——bzoj2286
虚树的核心就是把关键点和关键点的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的更多相关文章
- 【BZOJ-2286】消耗战 虚树 + 树形DP
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2120 Solved: 752[Submit][Status] ...
- bzoj 2286(虚树+树形dp) 虚树模板
树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5002 Sol ...
- 【BZOJ-3572】世界树 虚树 + 树形DP
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1084 Solved: 611[Submit][Status ...
- BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca
BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...
- BZOJ5341[Ctsc2018]暴力写挂——边分治+虚树+树形DP
题目链接: CSTC2018暴力写挂 题目大意:给出n个点结构不同的两棵树,边有边权(有负权边及0边),要求找到一个点对(a,b)满足dep(a)+dep(b)-dep(lca)-dep'(lca)最 ...
- [WC2018]通道——边分治+虚树+树形DP
题目链接: [WC2018]通道 题目大意:给出三棵n个节点结构不同的树,边有边权,要求找出一个点对(a,b)使三棵树上这两点的路径权值和最大,一条路径权值为路径上所有边的边权和. 我们按照部分分逐个 ...
- 2018.09.25 bzoj3572: [Hnoi2014]世界树(虚树+树形dp)
传送门 虚树入门题? 好难啊. 在学习别人的写法之后终于过了. 这道题dp方程很好想. 主要是不好写. 简要说说思路吧. 显然最优值只能够从子树和父亲转移过来. 于是我们先dfs一遍用儿子更新父亲,然 ...
- BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 4261 Solved: 1552 [Submit][Sta ...
- 【BZOJ2286】【SDOI2011】消耗战 [虚树][树形DP]
消耗战 Time Limit: 20 Sec Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一场战争中,战场由n个岛屿和n-1 ...
- 2018.09.25 bzoj2286: [Sdoi2011]消耗战(虚树+树形dp)
传送门 又一道虚树入门题. 这个dp更简单啊. 直接记录每个点到1的距离,简单转移就行了. 代码: #include<bits/stdc++.h> #define N 250005 #de ...
随机推荐
- Oracle多表更新及MERGE命令和闪回机制还原数据表
一.多表更新 比如线上有个系统由于某一个模块出现异常,导致系统整体的数据出现了错误,需要你手动改写数据库错误,Oracle update语句更新的值来自另一张表 update语法最基本的格式为 UPD ...
- war包里面文件的修改方式
1 将war包移动到一个干净的路径下,使用 jar xvf ROOT.war 命令将war进行解压操作 2 修改相应的文件内容,修改想要修改的文件,比如web.xml 3 使用 j ...
- 计算机网络之IP地址与MAC地址
IP地址 IP地址(Internet Protocol Address): 缩写为IP Adress,是一种在Internet上的给主机统一编址的地址格式,也称为网络协议(IP协议)地址. 它为互联网 ...
- Vue学习笔记【9】——Vue指令之v-for和key属性
迭代数组(普通数组.对象数组) <ul> <li v-for="(item, i) in list">索引:{{i}} --- 姓名:{{item.name ...
- J2EE学习篇之--JQuery技术详解
前面我们讲解了的J2EE的技术都是服务端的技术,下面我们来看一下前端的一些开发技术,这一篇我们来看一下jQuery技术 简介: jQuery由美国人John Resig创建,至今已吸引了来自世界各地的 ...
- Delphi 实现最近打开文件记录菜单
unit UntOpenMenu; //download by http://wwww.NewXing.com interface uses Windows, Messages, SysUtils, ...
- NX二次开发-基于NX开发向导模板的NX对Excel读写操作(OLE方式(COM组件))
在看这个博客前,请读者先去完整看完:NX二次开发-基于MFC界面的NX对Excel读写操作(OLE方式(COM组件))https://ufun-nxopen.blog.csdn.net/article ...
- 天梯L3-003. 社交集群——并查集
在社交网络平台注册时,用户通常会输入自己的兴趣爱好,以便找到和自己兴趣相投的朋友.有部分兴趣相同的人们就形成了“社交集群”.现请你编写程序,找出所有的集群. 输入格式: 输入的第一行给出正整数N(&l ...
- 计算1到N中包含数字1的个数
转自:http://pandonix.iteye.com/blog/204840 Mark N为正整数,计算从1到N的所有整数中包含数字1的个数.比如,N=10,从1,2...10,包含有2个数字1. ...
- cd 命令行进入目标文件夹
当我在默认路径中使用cd命令时,如果我要进入D:\mytext 文件夹,那么直接使用cd D:\mytext 是不行的 正确的使用是先使用d:进入D盘,然后再进入mytext文件夹