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). 对于两个要删除的 ...
随机推荐
- GeoServer安装配置
需安装文件 1.安装jdk 2.安装GeoServer: (1).在安装GeoServer前,需要安装java运行环境,点击文件夹内的jdk安装文件,选择jdk安装路径进行安装:直到安装完成. (2) ...
- Fragment与Activity的接口回调
这里说一个官方推荐的写法: private OnFragmentInteractionListener mListener; @Override public void onAttach(Contex ...
- SQL 创建分区表
(以项目中实际使用的GNSS库为例) 背景:数据量巨大,定时创建月表存放数据,月表中数据存放在不同的文件组中来提高查询效率 一.创建数据库,添加文件组 除了逻辑文件和物理文件的分离之外,SQL S ...
- Django 【认证系统】auth
本篇内容 介绍Django框架提供的auth 认证系统 方法: 方法名 备注 create_user 创建用户 authenticate 登录验证 login 记录登录状态 logout 退出用户登录 ...
- HBase实践案例:车联网监控系统
项目背景 本项目为车联网监控系统,系统由车载硬件设备.云服务端构成.车载硬件设备会定时采集车辆的各种状态信息,并通过移动网络上传到服务器端.服务器端接收到硬件设备发送的数据首先需要将数据进行解析,校验 ...
- 【spring源码分析】准备工作
前言:之前写过两篇基于xml形式的IOC容器初始化过程,现在看来写的比较烂,最近又继续阅读spring源码,对IOC容器的初始化有了一些新的认识,因此决定记录下来,加深自己对spring的印象与理解. ...
- springboot操作mongodb
springboot操作mongodb 采用MongoRepository操作mongodb springboot版本2.1.2.RELEASE 注意的是:在运行应用程序时,会报错OSS Algori ...
- 【模板】 $\text{K}$ 短路
Tags 搜索.\(\text{A*}\).很酷很炫的算法 定义二元组\(\text{DIS(X,Now)}\)表示到达\(\text{X}\)点,路程是\(\text{Now}\): 反向\(\te ...
- 问题记录2019-03-06(todo)
RuntimeError: maximum recursion depth exceeded while calling a Python object
- 在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)
本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...