题目:给出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的更多相关文章

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

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

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

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

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

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

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

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

  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. BZOJ.2286.[SDOI2011]消耗战(虚树 树形DP)

    题目链接 BZOJ 洛谷P2495 树形DP,对于每棵子树要么逐个删除其中要删除的边,要么直接断连向父节点的边. 如果当前点需要删除,那么直接断不需要再管子树. 复杂度O(m*n). 对于两个要删除的 ...

随机推荐

  1. angular打包后路由和文件路径不对

    base href换成如下script标签 <!-- <base href="/"> --> <script> document.write(' ...

  2. AI时代大点兵-国内外知名AI公司2018年最新盘点

    AI时代大点兵-国内外知名AI公司2018年最新盘点 导言 据腾讯研究院统计,截至2017年6月,全球人工智能初创企业共计2617家.美国占据1078家居首,中国以592家企业排名第二,其后分别是英国 ...

  3. Android ContenObserver 监听联系人数据变化

    一.知识介绍 1.ContentProvider是内容提供者 ContentResolver是内容解决者(对内容提供的数据进行操作) ContentObserver是内容观察者(观察内容提供者提供的数 ...

  4. 基于WanAndroid开放API实现的文章阅读APP

    简介 基于WanAndroid开放API开发的技术文章阅读App.主要功能包括:首页.体系.项目.公众号.搜索.登录.收藏.夜间模式等. 用到的第三方框架 RxJava RxAndroid Retro ...

  5. Redis压缩列表

    此篇文章是主要介绍Redis在数据存储方面的其中一种方式,压缩列表.本文会介绍1. 压缩列表(ziplist)的使用场景 2.如何达到节约内存的效果?3.压缩列表的存储格式 4. 连锁更新的问题  5 ...

  6. SQL Server Mirror 断开后,删除副本上镜像数据库

    一般而言,SQL Server 在数据库级别进行数据同步的方式主要有三种 1.日志传送:2.Mirror(镜像):3. AlwaysOn.复制订阅技术理解为表级别的同步,不归结为数据库级别的同步. 在 ...

  7. 第一个 java 程序

    java程序的运行机制 JVM实现了跨平台 JDK > JRE > JVM java Development Kit(JDK)包含:JRE,以及增加编译器和调试器等用于程序开发的文件 Ja ...

  8. python正则表达式模块re

    正则表达式的特殊元素 匹配符号 描述 '.'(点dot) 在默认模式下,它匹配除换行符之外的任何字符.如果指定了DOTALL标志,则匹配包括换行符在内的任何字符 '^'(Caret) 匹配以字符串开头 ...

  9. python3打印当前时间和获取程序运行时间

    学习使用time模块和datetime模块. 通常我们想让程序等待几秒钟,再继续向下运行,time模块的sleep()方法是一个很好的选择.但是想通过time模块打印系统的当前时间,则比较麻烦.如下: ...

  10. mysql8.0版本修改密码

    登录之后使用如下命令: ALTER USER 'root'@'localhost' IDENTIFIED BY "你的新密码"; 还有不知是不是因为mysql版本问题,一开始设置的 ...