图论&动态规划:虚树
虚树可以看做是对树形动态规划的一种求解优化
对于需要求答案的点p,只保留对答案有影响的节点,从而减少时间
BZOJ2286
dp[i]=min(val[i],Σdp[j](j为i的儿子)),val[i]表示将i和根节点分离的代价
方程为什么这么写呢?val也就是从当前i到根节点的边权的最小值
为了让代价最小,最后的dp[root]就是答案了,树形dp是先递归调用到根然后回溯的过程中求值,回溯到根节点的时候答案就显然了
我们可以只用询问点及他们的LCA来建一颗新树,我们暂且称其为虚树,然后在虚树上跑dp,效率就会高很多
维护虚树的过程我没有看懂,只能参考程序了,用栈维护的
每次按照关键点的dfs序排序,维护栈构建一棵新的树,在新的树上dp
#include<iostream>
#include<set>
#include<map>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<bitset>
#include<stack>
#define inf 1e60
#define pa pair<int,int>
#define ll long long
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int bin[];
int n,m,cnt,ind,top;
int last[],last2[],fa[][];
ll mn[],f[];
int h[],mark[],deep[];
int st[];
struct edge{
int to,next,v;
}e[],ed[];
void insert(int u,int v,int w)
{
e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=w;
}
void insert2(int u,int v)
{
if(u==v)return;
ed[++cnt].to=v;ed[cnt].next=last2[u];last2[u]=cnt;
}
bool cmp(int a,int b)
{
return mark[a]<mark[b];
}
void pre(int x)
{
mark[x]=++ind;
for(int i=;bin[i]<=deep[x];i++)
fa[x][i]=fa[fa[x][i-]][i-];
for(int i=last[x];i;i=e[i].next)
if(e[i].to!=fa[x][])
{
mn[e[i].to]=min(mn[x],(ll)e[i].v);
deep[e[i].to]=deep[x]+;
fa[e[i].to][]=x;
pre(e[i].to);
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int t=deep[x]-deep[y];
for(int i=;bin[i]<=t;i++)
if(t&bin[i])x=fa[x][i];
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
if(x==y)return x;
return fa[x][];
}
void dp(int x)
{
f[x]=mn[x];
ll tmp=;
for(int i=last2[x];i;i=ed[i].next)
{
dp(ed[i].to);
tmp+=f[ed[i].to];
}
last2[x]=;
if(tmp==)f[x]=mn[x];
else if(tmp<=f[x])f[x]=tmp;
}
void solve()
{
cnt=;
int K=read();
for(int i=;i<=K;i++)
h[i]=read();
sort(h+,h+K+,cmp);
int tot=;
h[++tot]=h[];
for(int i=;i<=K;i++)
if(lca(h[tot],h[i])!=h[tot])h[++tot]=h[i];
st[++top]=;
for(int i=;i<=tot;i++)
{
int now=h[i],f=lca(now,st[top]);
while()
{
if(deep[f]>=deep[st[top-]])
{
insert2(f,st[top--]);
if(st[top]!=f)st[++top]=f;
break;
}
insert2(st[top-],st[top]);top--;
}
if(st[top]!=now)st[++top]=now;
}
while(--top)insert2(st[top],st[top+]);
dp();
printf("%lld\n",f[]);
}
int main()
{
bin[]=;for(int i=;i<;i++)bin[i]=bin[i-]<<;
n=read();
for(int i=;i<n;i++)
{
int u=read(),v=read(),w=read();
insert(u,v,w);
}
mn[]=inf;pre();
m=read();
for(int i=;i<=m;i++)
solve();
return ;
}
图论&动态规划:虚树的更多相关文章
- 【WC2018】通道(边分治,虚树,动态规划)
[WC2018]通道(边分治,虚树,动态规划) 题面 UOJ 洛谷 题解 既然是三棵树,那么显然就是找点什么东西来套个三层. 一棵树怎么做?入门dp. 两棵树?假设在第一棵树中的深度为\(dep\). ...
- 【CF809E】Surprise me!(动态规划,虚树,莫比乌斯反演)
[CF809E]Surprise me!(动态规划,虚树,莫比乌斯反演) 题面 洛谷 CodeForces 翻译: 给定一棵\(n\)个节点的树,每个点有一个权值\(a[i]\),保证\(a[i]\) ...
- 【CF613D】Kingdom and its Cities(虚树,动态规划)
[CF613D]Kingdom and its Cities(虚树,动态规划) 题面 洛谷 CF 翻译洛谷上有啦 题解 每次构建虚树,首先特判无解,也就是关键点中存在父子关系. 考虑\(dp\),设\ ...
- 【BZOJ3611】大工程(虚树,动态规划)
[BZOJ3611]大工程(虚树,动态规划) 题面 BZOJ Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树 ...
- 【BZOJ2286】消耗战(虚树,动态规划)
[BZOJ2286]消耗战(虚树,动态规划) 题面 BZOJ Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总 ...
- 数据结构(虚树,动态规划):HNOI 2014 世界树
Hnoi2014 世界树 Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平 ...
- 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)
orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...
- 「洛谷2495」「BZOJ3052」「SDOI2001」消耗战【虚树+树形动态规划】
题目大意 给你\(k\)个点,让这一些点和一号节点断开,删去某一些边,求最小的删去边权之和. 做题的心路历程 做了\(HG\)昨天的模拟赛,深深感觉到了窝的菜,所以为了\(A\)掉T1这一道毒瘤,窝就 ...
- BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序
https://www.lydsy.com/JudgeOnline/problem.php?id=2286 wa了两次因为lca犯了zz错误 这道题如果不多次询问的话就是裸dp. 一棵树上多次询问,且 ...
随机推荐
- 《C》数组
数组 数组方法: var arr = [1, 2, 3]; arr.push(4)://arr='[1, 2, 3, 4]' 向末尾添加一个或者多个元素 arr.pop()://删除末位元素 var ...
- ubuntu下配置ss并设置PAC模式
一.安装ss 1. sudo apt-get update(更新源) 2. sudo apt-get install python-pip(安装pip) 3. sudo pip install sha ...
- MySQL的并发访问控制(锁)
前言:任何的数据集只要支持并发访问模型就必须基于锁机制进行访问控制 锁种类 读锁:共享锁,允许给其他人读,不允许他人写写锁:独占锁, 不允许其他人读和写 锁类型 显示锁:用户手动请求读锁或写锁隐式锁: ...
- Hibernate 应知应会
Hibernate 的关联关系的配置: 一对一外键约束: 举例子是一个丈夫和妻子:[一个丈夫只能有一位妻子] 表结构: CREATE TABLE `tbl_hus` ( `uuid` ) NOT NU ...
- java中枚举型的定义以及使用
1.如何定义枚举型 public enum gender{ GEN1("男","1"), GEN2("女","0"); ...
- C++解析(29):类型识别
0.目录 1.类型识别 2.动态类型识别 3.类型识别关键字 4.小结 1.类型识别 在面向对象中可能出现下面的情况: 基类指针指向子类对象 基类引用成为子类对象的别名 静态类型--变量(对象)自身的 ...
- 深入理解JVM一垃圾回收器
上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中,用户可以根据自身的需求,使用不同的垃 ...
- 深入理解JVM一配置参数
一.JVM配置参数分为三类参数: 1.跟踪参数 2.堆分配参数 3.栈分配参数 这三类参数分别用于跟踪监控JVM状态,分配堆内存以及分配栈内存. 二.跟踪参数 跟踪参数用于跟踪监控JVM,往往被开发人 ...
- 【刷题】BZOJ 3238 [Ahoi2013]差异
Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N< ...
- Ckeditor与Ckfinder(java)整合实现富媒体内容编辑(支持文件上传)
先来看一下最终的效果图 一.编辑器界面 二.上传图片界面 <!-------------------------------------------------------> 一.安装包下 ...