P2495 [SDOI2011]消耗战 lca倍增+虚树+树形dp
题目:给出n个点的树 q次询问 问切断 k个点(不和1号点联通)的最小代价是多少
思路:树形dp sum[i]表示切断i的子树中需要切断的点的最小代价是多少 mi[i]表示1--i中的最小边权
sum[i]=min(mi[i],sigma(min(mi[v],sum[v]) (v∈i.son))
从根向上dp 这里巧妙运用了欧拉序(每个点入和出的按时间顺序排列的序列)
题目链接:https://www.luogu.org/problemnew/show/P2495
参考:https://www.luogu.org/problemnew/solution/P2495
#include<bits/stdc++.h>
using namespace std;
const int maxn = ;
typedef long long ll;
const int N=maxn;
struct data{
int v;int nxt;ll val;
}edge[*maxn];
int dfu;
int dfin[N];//欧拉序入的时间戳
int dfou[N];//欧拉序列出的时间戳
int fa[][N];//倍增用
ll mi[N];//i到1号点路径中最小的边权
int dep[N]; //深度
int lca(int u,int v){//倍增lca
if(dep[u]<dep[v])swap(u,v);
int del=dep[u]-dep[v];
for(int i=;del;del>>=,i++){
if(del&){
u=fa[i][u];
}
}//到同一深度
if(u==v)return u;
for(int i=;i>=;i--){
if(fa[i][u]!=fa[i][v]){u=fa[i][u],v=fa[i][v];}
} //从到lca的距离的二进制理解 即可立即为什么fa[0][v]就是是lca
return fa[][v];
}
int alist[maxn],cnt;int n; void dfs(int x){
dfin[x]=++dfu;//首位是入 出 时间戳
for(int i=;fa[i-][x];i++){//更新父节点信息
fa[i][x]=fa[i-][fa[i-][x]];
}
int nxt=alist[x];
while(nxt){//更新最小边权
int v=edge[nxt].v,val=edge[nxt].val;
if(dfin[v]==){
dep[v]=dep[x]+;
mi[v]=min(mi[x],1ll*val);
fa[][v]=x;
dfs(v);
}
nxt=edge[nxt].nxt;
}
dfou[x]=++dfu;
return ;
}
inline void add(int u,int v,ll val)
{ edge[++cnt].v=v;
edge[cnt].nxt=alist[u];
alist[u]=cnt;
edge[cnt].val=val;
}
bool cmp(int x,int y){//分为正负即可方便得判断是入 还是出
int k1=(x>)?dfin[x]:dfou[-x];
int k2=(y>)?dfin[y]:dfou[-y];
return k1<k2;
}
int tr[*N];
stack<int>s;
int m;
bool book[N];
ll sum[N]; int main(){
scanf("%d",&n);
for(int i=;i<=n-;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
mi[]=0x3f3f3f3f;
dfs();//建立欧拉序
scanf("%d",&m);
for(int i=;i<=m;i++){
int tmp;
scanf("%d",&tmp);
for(int j=;j<=tmp;j++){//把要求的点标记
scanf("%d",&tr[j]);
book[tr[j]]=;
sum[tr[j]]=mi[tr[j]];//初始化删除重要点的sum[i](sum指的是切断[i]的子树中所有重要点的最小代价 初始化为切掉该点即 从1--i的最小边权 意思是直接把这个子树切掉了)
}
sort(tr+,tr+tmp+,cmp);//对欧拉序列排序建立虚树
for(int j=;j<tmp;j++){
int lc=lca(tr[j],tr[j+]);
if(!book[lc]){//树的建立
tr[++tmp]=lc;
book[lc]=;
}
}
int nc=tmp;
for(int j=;j<=nc;j++){//把每个点的负时间戳也加入 用负数表示这个的点现在是出去的点
tr[++tmp]=-tr[j];
}
if(!book[]){//强行把1号点加进来当根
tr[++tmp]=;tr[++tmp]=-;
}
sort(tr+,tr+tmp+,cmp);//重构欧拉序
for(int j=;j<=tmp;j++){//模拟dfs 因为1--tmp是欧拉序列 所以可以直接用
if(tr[j]>)s.push(tr[j]);//进栈
else {
int now=s.top();s.pop();
if(now!=){
//状态转移方程sum[i]=sigma(min(mi[v],sum[v]) (v∈i.son)
int fa=s.top();
sum[fa]+=min(sum[now],mi[now]);
}
else printf("%lld\n",sum[]);
sum[now]=;
book[now]=false;
}
}
} return ;
}
P2495 [SDOI2011]消耗战 lca倍增+虚树+树形dp的更多相关文章
- BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca
BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...
- 【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 ...
- 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 ...
- BZOJ.2286.[SDOI2011]消耗战(虚树 树形DP)
题目链接 BZOJ 洛谷P2495 树形DP,对于每棵子树要么逐个删除其中要删除的边,要么直接断连向父节点的边. 如果当前点需要删除,那么直接断不需要再管子树. 复杂度O(m*n). 对于两个要删除的 ...
随机推荐
- 【Vue 2.x】指令的学习
v-on作用于事件,简写@ v-bind作用于html元素的属性,简写: v-for作用于模板内的变量,和C#的foreach类似的用法 v-if和v-show条件渲染html元素 v-model ...
- 惊喜,重磅福利!免费开源ERP-企业信息化金矿
Odoo,以前叫OpenERP,是比利时Odoo S.A.公司开发的一个企业应用软件套件,开源套件包括一个企业应用快速开发平台,以及几千个Odoo及第三方开发的企业应用模块.Odoo适用于各种规模的企 ...
- MongoDB在Linux下常用优化设置
MongoDB在Linux下常用优化设置 以下是一些MongoDB推荐的常用优化设置.在生产环境下选取合适的参数值,例如预读值和默认文件描述符数目等,会对系统性能有很大的影响. 1.关闭数据库文件的 ...
- 从零学习Fluter(七):Flutter打包apk详解
写一个win上 flutter 打包apk的教程 这篇文档介绍一下flutter打包发布正式版apk 整体来看,和命令行打包rn的方法相差不大 打包前先做检查工作&查看构建配置 Android ...
- 第三篇 Html-label标签
label标签 用户获取文字,使得关联的标签获取光标 <!DOCTYPE html> <html lang="en"> <head> <m ...
- ASP.NET Zero--前期要求
前期要求 需要以下工具才能使用ASP.NET Zero Core解决方案: Visual Studio 2017 + Visual Studio扩展: Bundler&Minifier Web ...
- anaconda --包管理和环境管理器
前言: 以下所有的命令都Win10环境的 Anaconda Prompt 中 环境管理 创建虚拟环境 conda create --name env_name python 也可以指定 Python ...
- 前后端分离djangorestframework—— 接入微信模板消息推送
微信 什么是微信也不多说,跟前面的支付宝一样的 微信支付 微信支付也有个沙箱环境,沙箱环境官方文档 由文档中那句很显眼的话所得,即使是测试环境也需要真实的商户号,所以这个就没法想支付宝那样用沙箱账号来 ...
- java类加载及类初始化
1.前言 java是跨平台语言,主要是因为它的java虚拟机的存在,java有事编译语言,所以需要将编写的java文件编译成jvm可运用的class字节码文件.在java中一切皆对象.对于Java虚拟 ...
- Java使用volatile实现多线程输出ABC共10次
问题 有A,B,C三个线程, A线程输出A, B线程输出B, C线程输出C.要求,同时启动三个线程, 按顺序输出ABC, 循环10次. 今天在写多线程的时候找例子,见到了这样一个题,觉得不难,但是在网 ...