洛谷P2495 [SDOI2011]消耗战(虚树dp)
P2495 [SDOI2011]消耗战
题解:
虚树\(dp\)入门题吧。虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是一样的,所以可以就求出dfs序并且利用它来构造。最后的图中只有关键点以及某些关键点对的lca。
具体构造方法就是利用一个栈,假设当前插入结点为\(x\),求出栈顶元素和\(x\)的lca,如果栈顶元素为lca,那么我们就继续延长这条链;否则(此时栈顶元素和\(x\)在lca的两颗子树上面)就将栈顶元素到\(lca\)上面的点弹出来并且建边,然后继续延长\(x\)这边的链。
感觉说得不是很清楚,详见代码吧:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 250005 ;
int n, m;
struct Edge{
int v, next, w;
}e[N << 1];
int head[N], tot;
void adde(int u, int v, int w) {
e[tot].v = v; e[tot].w = w; e[tot].next = head[u]; head[u] = tot++;
}
vector <int> g[N] ;
int f[N][20], deep[N], dfn[N];
ll mn[N];
int T;
void dfs(int u, int fa) {
deep[u] = deep[fa] + 1;
dfn[u] = ++T;
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if(v == fa) continue ;
mn[v] = min((ll)e[i].w, mn[u]) ;
f[v][0] = u;
for(int j = 1; j <= 17; j++) f[v][j] = f[f[v][j - 1]][j - 1] ;
dfs(v, u) ;
}
}
int LCA(int x, int y) {
if(deep[x] < deep[y]) swap(x, y) ;
for(int i = 17; i >= 0; i--) {
if(deep[f[x][i]] >= deep[y]) x = f[x][i] ;
}
if(x == y) return x;
for(int i = 17; i >= 0; i--) {
if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i] ;
}
return f[x][0] ;
}
int sta[N], a[N];
int top;
bool cmp(const int &x, const int &y) {
return dfn[x] < dfn[y] ;
}
void add_edge(int u, int v) {
g[u].push_back(v) ;
}
void insert(int x) {
int lca = LCA(x, sta[top]) ;
if(top == 1) {sta[++top] = x; return ;}
if(lca == sta[top]) return ;
while(top > 1 && dfn[sta[top - 1]] >= dfn[lca]) {
add_edge(sta[top - 1], sta[top]); top--;
}
if(sta[top] != lca) add_edge(lca, sta[top]), sta[top] = lca;
sta[++top] = x;
}
ll DP(int u) {
if(g[u].size() == 0) return mn[u];
ll sum = 0;
for(auto v : g[u]) sum += DP(v) ;
g[u].clear() ;
return min(sum, (ll)mn[u]) ;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
mn[1] = 1ll << 56;
memset(head, -1, sizeof(head)) ;
for(int i = 1; i < n; i++) {
int u, v, w;
cin >> u >> v >> w;
adde(u, v, w); adde(v, u, w) ;
}
dfs(1, 0) ;
cin >> m;
while(m--) {
int k; cin >> k;
for(int i = 1; i <= k; i++) cin >> a[i] ;
sort(a + 1, a + k + 1, cmp) ;
sta[top = 1] = 1;
for(int i = 1; i <= k; i++) insert(a[i]) ;
while(top > 1) add_edge(sta[top - 1], sta[top]), top--;
cout << DP(1) << '\n' ;
}
return 0 ;
}
洛谷P2495 [SDOI2011]消耗战(虚树dp)的更多相关文章
- bzoj 2286(洛谷 2495) [Sdoi2011]消耗战——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2286 https://www.luogu.org/problemnew/show/P2495 ...
- 洛谷 P2495 [SDOI2011]消耗战(虚树,dp)
题面 洛谷 题解 虚树+dp 关于虚树 了解一下 具体实现 inline void insert(int x) { if (top == 1) {s[++top] = x; return ;} int ...
- [BZOJ2286][SDOI2011]消耗战(虚树DP)
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4998 Solved: 1867[Submit][Statu ...
- ●洛谷P2495 [SDOI2011]消耗战
题链: https://www.luogu.org/problemnew/show/P2495题解: 虚树入门,树形dp 推荐博客:http://blog.csdn.net/lych_cys/arti ...
- bzoj 2286 [Sdoi2011]消耗战 虚树+dp
题目大意:多次给出关键点,求切断边使所有关键点与1断开的最小费用 分析:每次造出虚树,dp[i]表示将i和i子树与父亲断开费用 对于父亲x,儿子y ①y为关键点:\(dp[x]\)+=\(dismn( ...
- 【BZOJ】2286: [Sdoi2011]消耗战 虚树+DP
[题意]给定n个点的带边权树,每次询问给定ki个特殊点,求隔离点1和特殊点的最小代价.n<=250000,Σki<=500000. [算法]虚树+DP [题解]考虑普通树上的dp,设f[x ...
- 洛谷P2495 [SDOI2011]消耗战(虚树)
题面 传送门 题解 为啥一直莫名其妙\(90\)分啊--重构了一下代码才\(A\)掉-- 先考虑直接\(dp\)怎么做 树形\(dp\)的时候,记一下断开某个节点的最小值,就是从根节点到它的路径上最短 ...
- [洛谷P2495][SDOI2011]消耗战
题目大意:有一棵$n(n\leqslant2.5\times10^5)$个节点的带边权的树,$m$个询问,每次询问给出$k(\sum\limits_{i=1}^mk_i\leqslant5\times ...
- 洛谷 P3233 [HNOI2014]世界树(虚树+dp)
题面 luogu 题解 数据范围已经告诉我们是虚树了,考虑如何在虚树上面\(dp\) 以下摘自hzwer博客: 构建虚树以后两遍dp处理出虚树上每个点最近的议事处 然后枚举虚树上每一条边,考虑其对两端 ...
随机推荐
- 数据分析,R语言
数据结构 创建向量和矩阵 1 函数c(), length(), mode(), rbind(), cbind() 求平均值,和,连乘,最值,方差,标准差 1 函数mean(), sum(), min( ...
- Django RestFramework中UpdateAPIView类使用
修改数据 from django.conf.urls import url from .api import workflow,workflowline urlpatterns = [ url(r'^ ...
- [原创]UnLua Emmylua UE4开发环境搭建
前言 公司开发的第二个虚幻4项目已经上线了,慢慢趋于稳定.回想起开荒的日子,历历在目.从引擎脚本的选择,各工具(导表,协议生成...)的重构.开发, 引擎扩展(多骨骼支持,Notify扩展,技能编辑器 ...
- 记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法
记一次查询超时的解决方案The timeout period elapsed...... https://www.cnblogs.com/wyt007/p/9274613.html Exception ...
- 【神经网络与深度学习】DCGAN及其TensorFlow源码
上一节我们提到G和D由多层感知机定义.深度学习中对图像处理应用最好的模型是CNN,那么如何把CNN与GAN结合?DCGAN是这方面最好的尝试之一.源码:https://github.com/Newmu ...
- [转帖]UML类图关系图解
UML类图关系图解 https://www.cnblogs.com/TvvT-kevin/p/9357339.html 一.类结构 在类的UML图中,使用长方形描述一个类的主要构成,长方形垂直地分为三 ...
- 【Pandas教程】像写SQL一样用Pandas~
写在最前 Python在数据分析领域有三个必须需要熟悉的库,分别是pandas,numpy和matplotlib,如果排个优先级的话,我推荐先学pandas. numpy主要用于数组和矩阵的运算,一般 ...
- Django ORM 数据库增删改查
Django ORM 数据库增删改查 增 # 创建.增加数据(推荐) models.UserInfo.objects.create(username=') # 创建.增加数据 dic = {'} mo ...
- Linux中最大进程数和最大文件数
前言 Linux系统中可以设置关于资源的使用限制,比如:进程数量,文件句柄数,连接数等等. 在日常的工作中应该遇到过: -bash: fork: retry: Resource temporarily ...
- 通过静态发现方式部署 Etcd 集群
在「etcd使用入门」一文中对etcd的基本知识点和安装做了一个简要的介绍,这次我们来说说如何部署一个etcd集群. etcd构建自身高可用集群主要有三种形式: 静态发现: 预先已知etcd集群中有哪 ...