P2495 [SDOI2011]消耗战

树形dp
状态表示:fuf_ufu​表示以uuu为根的子树中,uuu节点与子树中的关键的“隔开”所需要的最小代价
状态转移:
考虑uuu的一个儿子vvv

于是有下面暴力代码O(nm+∑k)O(nm+\sum k)O(nm+∑k)

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
//#pragma GCC optimize(2)
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
using ll=long long;
constexpr int N=250010;
int h[N],e[2*N],ne[2*N],w[2*N],idx;
void add(int a,int b,int c){e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;}
ll f[N];
int n,m;
bool mp[N];
void dfs(int u,int fa)
{for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs(v,u);if(mp[v]) f[u]+=w[i];elsef[u]+=min((ll)w[i],f[v]);}
}
int main()
{IO;cin>>n;memset(h,-1,sizeof h);for(int i=1;i<n;i++){int a,b,c;cin>>a>>b>>c;add(a,b,c),add(b,a,c);}cin>>m;while(m--){memset(f,0ll,sizeof(ll)*(n+1));memset(mp,0,sizeof(bool)*(n+1));int k;cin>>k;while(k--){int p;cin>>p;mp[p]=1;}dfs(1,0);cout<<f[1]<<'\n';}return 0;
}

虚树-树上动态规划的利器
oiwiki虚树

虚树:根据原树构建一颗虚拟的树,这棵树只包含{\color{red}只包含}只包含关键节点以及关键节点的最近公共祖先(LCA)

构建过程:

  • 将关键节点的时间戳排序
  • 用一个栈维护一条虚树上的链,根节点到当前关键节点,将关键点依次push进栈中

push过程:
大佬图片非常清晰
下面用top表示栈顶元素,cur表示当前需要插入的节点
anc=lca(top,cur)
首先如果说anc=top,说明cur应该接在栈顶后面即可

否则会出现下面情况


当前栈中维护的是绿色{\color{green}绿色}绿色的那一条链,我们需要让当前栈维护从根节点到当前节点即蓝色{\color{blue}蓝色}蓝色那条链,只需要让top-1向top连边,并且不断top- -即可。

最后需要判断是否存在下面情况
如果存在,需要连一条anc到top的边,然后弹出top- -,并将anc入栈

代码如下

void insert(int u)
{int anc=lca(u,stk[tt]);while(tt>1&&dfn[stk[tt-1]]>=dfn[anc])E[stk[tt-1]].push_back(stk[tt]),tt--;if(stk[tt]!=anc) E[anc].push_back(stk[tt]),stk[tt]=anc;//最后的情况stk[++tt]=u;
}
void build()// 构建虚树
{sort(is+1,is+1+m,[](const int &a,const int &b){return dfn[a]<dfn[b];});//按照dfn排序stk[tt=1]=1;//根节点for(int i=1;i<=m;i++) insert(is[i]);while(tt) E[stk[tt-1]].push_back(stk[tt]),tt--;// 连边
}

显然虚树两点(u,v)之间边u→vu\to vu→v的大小应为原树中路径min⁡(u⇝v)\min(u \leadsto v)min(u⇝v),倍增求lca过程即可求出边权。

而下面代码采取另一种做法:
首先预处理原树中根节点到当前节点路径的最小值
dpudp_udpu​表示从u开始不能到达其子树中的关键点所需切断的最小边权和。
切断儿子vvv要么用mn[v]mn[v]mn[v]要么切断子树,如果当前节点是关键节点,必须切断当前节点即花费代价为mn[u]mn[u]mn[u]

注意:虚树清空节点需要在dfs过程中清空,不能使用memset

时间复杂度∑klog⁡n\sum k\log n∑klogn

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
//#pragma GCC optimize(2)
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
using ll=long long;
constexpr int N=250010;
int h[N],e[2*N],ne[2*N],w[2*N],idx;
void add(int a,int b,int c){e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;}int dep[N],sz[N],son[N],fa[N];
int mn[N];
void dfs1(int u)
{sz[u]=1;for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa[u]) continue;fa[v]=u;dep[v]=dep[u]+1;mn[v]=min(mn[u],w[i]);dfs1(v);sz[u]+=sz[v];if(sz[son[u]]<sz[v]) son[u]=v;}
}
int top[N],dfn[N],timestamp;
void dfs2(int u,int t)
{dfn[u]=++timestamp;top[u]=t;if(!son[u]) return;dfs2(son[u],t);for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa[u]||v==son[u]) continue;dfs2(v,v);}
}
int lca(int u,int v)
{while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]]) swap(u,v);u=fa[top[u]];}return dep[u]<dep[v]?u:v;
}
//====================================================树剖求lca
int n,m;
int stk[N],tt;
int is[N];
bool mp[N];
vector<int> E[N];
void insert(int u)
{int anc=lca(u,stk[tt]);while(tt>1&&dfn[stk[tt-1]]>=dfn[anc])E[stk[tt-1]].push_back(stk[tt]),tt--;if(stk[tt]!=anc) E[anc].push_back(stk[tt]),stk[tt]=anc;stk[++tt]=u;
}
void build()// 构建虚树
{sort(is+1,is+1+m,[](const int &a,const int &b){return dfn[a]<dfn[b];});//按照dfn排序stk[tt=1]=1;//根节点for(int i=1;i<=m;i++) insert(is[i]);while(tt) E[stk[tt-1]].push_back(stk[tt]),tt--;
}
ll dfs3(int u)
{ll cost=0;for(int v:E[u]) cost+=min((ll)mn[v],dfs3(v));E[u].clear();if(mp[u]) return mn[u];else return cost;
}
int main()
{IO;cin>>n;memset(h,-1,sizeof h);memset(mn,0x3f,sizeof mn);for(int i=1;i<n;i++){int a,b,c;cin>>a>>b>>c;add(a,b,c),add(b,a,c);}dfs1(1);dfs2(1,1);int q;cin>>q;while(q--){cin>>m;for(int i=1;i<=m;i++){cin>>is[i];mp[is[i]]=1;}build();cout<<dfs3(1)<<'\n';for(int i=1;i<=m;i++) mp[is[i]]=0;}return 0;
}

要加油哦~

P2495 [SDOI2011]消耗战(树形dp+虚树)相关推荐

  1. 洛谷P2495 [SDOI2011]消耗战(虚树dp)

    P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...

  2. P2495 [SDOI2011]消耗战

    P2495 [SDOI2011]消耗战 虚树+dpdpdp. 每次在整个图上跑dpdpdp时间肯定不够,所以考虑只对查询点和其lcalcalca进行建图. 此题的dpdpdp转移有两种方式:一种是直接 ...

  3. 旅游(树形dp求树的最大独立集)

    链接:https://ac.nowcoder.com/acm/problem/15748 来源:牛客网 题目描述 Cwbc和XHRlyb生活在s市,这天他们打算一起出去旅游. 旅行地图上有n个城市,它 ...

  4. 树上子链(树形dp求树的直径)

    树上子链 题意: 给定一棵树 T ,树 T 上每个点都有一个权值. 定义一颗树的子链的大小为:这个子链上所有结点的权值和 . 请在树 T 中找出一条最大的子链并输出. 题解: 求树的直径,题目中存在负 ...

  5. P2495 [SDOI2011]消耗战-虚树+树形dp

    https://www.luogu.com.cn/problem/P2495 虚树:当我们在解决树形dp的问题的时候,题目中会给出一些询问,询问涉及的关键节点不多,并保证总的点数规模的时候,我们就可以 ...

  6. 虚树——P2495 [SDOI2011]消耗战

    好久没有学习新的知识了. https://www.luogu.com.cn/problem/P2495 今天我学习了一下虚树. 虚树就是一个不存在的树.用来简化问题.它只包括一些关键点和他的LCA 我 ...

  7. 洛谷 P2495 [SDOI2011]消耗战 虚树

    题目描述 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望.已知 ...

  8. 洛谷P2495 [SDOI2011]消耗战 | 一个典型的可以搞懂虚树的例题

    题目链接 题目大意: 给出一棵树,之后对这棵树进行q次询问,每次询问一个点集,给出使得这些点集中的点都不能直接或者间接的与1相连,需要删边的最小代价(边的代价在给树的时候给出),,点集不包含1,点集总 ...

  9. P2495 [SDOI2011]消耗战 虚树入门

    一棵树,n个点m个操作.每条边有权值,每个操作给你k个点,问断开若干条边后使k个点与根不相连的最小边权和是多少. 有sigmaK<500000 易知一个裸的树dp需要复杂度,m次操作后总复杂度为 ...

最新文章

  1. 开源生态也难逃“卡脖子”危机?中国AI开发者的警醒和突围
  2. ASP.NET 2.0 之 Master Page 学习笔记
  3. c语言银行家算法模拟程序,C语言实现 操作系统 银行家算法
  4. opencv和caffe编译后怎么添加路径
  5. python多线程queue_python多线程+队列(提高爬虫时效性)
  6. 你拿苹果技术顾问怎么办?
  7. c语言求栈长度程序,数据结构C语言实现之顺序栈
  8. python金融编程入门_python金融实务从入门到精通完整版
  9. 使用Banner制作轮播图
  10. 我的第一款(ban)产(cheng)品(pin)——铛铛打卡
  11. Remove or reset file passwords in Office 2013
  12. JSON解析基础使用知识-Java
  13. 七彩cms云转码_七彩CMS开源程序-最新云转码全开源 带完整安装搭建教程
  14. Ubuntu18下通过yolov5进行训练并预测
  15. XMPP协议和asmack
  16. 微信授权登录(java实现)
  17. 读书笔记——上瘾:让用户养成使用习惯的四大产品逻辑
  18. [漏洞复现]CVE-2021-26855 漏洞复现及Exchange邮箱详细安装过程
  19. 文本过长时中间部分用省略号表示。
  20. 腾讯企业容器云平台技术解析

热门文章

  1. iPad怎么分屏?学会这个方法,轻松拿捏
  2. 平衡二叉树(AVL)的左旋和右旋
  3. 五十分钟带你看遍C语言初阶语法(总纲)
  4. 在浙江php就业岗位,找工作的小伙伴快看过来!浙江多地最新教师就业岗位信息来了...
  5. impdp oracle 只导入表结构_Oracle数据导入导出(expdp impdp)
  6. java集成腾讯地图
  7. CSDN产品周报第19期|CodeChina正式更名为GitCode、不存在有效回答的免费提问也支持自主结题啦
  8. 强迫症的 Mac 设置指南
  9. 用SQL语句查询一个特定老师学生中男生女生各多少人
  10. 爱壁纸hd电脑版|爱壁纸hd电脑版下载