洛谷 P2495 [SDOI2011]消耗战(虚树,dp)
题面
题解
虚树+dp
关于虚树
了解一下
- 具体实现
 
inline void insert(int x) {
	if (top == 1) {s[++top] = x; return ;}
	int lca = query(x, s[top]);
	while (top > 1 && dfn[s[top-1]] >= dfn[lca]) t[s[top-1]].push_back(s[top]), top--;
	if (lca != s[top]) t[lca].push_back(s[top]), s[top] = lca;
	s[++top] = x;
	return ;
}
bool cmp(int a, int b) {
	return dfn[a] < dfn[b];
}//dfn为在dfs序上的位置
main() {//o为输入的关键点
	sort(o+1, o+1+k, cmp);
	s[top = 1] = 1;
	for (int i = 1; i <= k; i++) insert(o[i]);
    for (int i = 1; i < top; i++) t[s[i]].push_back(s[i+1]);
}
然后对于这个虚树\(dp\)
\(a\)数组表示当前点到根这条链路径最小值
Code
#include<bits/stdc++.h>
#define LL long long
#define RG register
using namespace std;
inline int gi() {
	RG int x = 0; RG char c = getchar(); bool f = 0;
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') c = getchar(), f = 1;
	while (c >= '0' && c <= '9') x = x*10+c-'0', c = getchar();
	return f ? -x : x;
}
const int N = 250010, INF = 2147483647;
struct node {
	int to, next, w;
}g[N<<1];
int last[N], gl;
inline void add(int x, int y, int z) {
	g[++gl] = (node) {y, last[x], z};
	last[x] = gl;
	return ;
}
int anc[N][21], dfn[N], cnt, dep[N], a[N];
void init(int u, int fa) {
	anc[u][0] = fa;
	dfn[u] = ++cnt;
	for (int i = 1; i <= 20; i++)
		anc[u][i] = anc[anc[u][i-1]][i-1];
	for (int i = last[u]; i; i = g[i].next) {
		int v = g[i].to;
		if (v == fa) continue;
		dep[v] = dep[u]+1;
		a[v] = min(g[i].w, a[u]);
		init(v, u);
	}
	return ;
}
inline int query(int x, int y) {
	if (dep[x] < dep[y]) swap(x, y);
	for (int i = 20; i >= 0; i--)
		if (dep[anc[x][i]] >= dep[y])
			x = anc[x][i];
	if (x == y) return x;
	for (int i = 20; i >= 0; i--)
		if (anc[x][i] != anc[y][i])
			x = anc[x][i], y = anc[y][i];
	return anc[x][0];
}
vector<int> t[N];
int o[N], s[N], top;
bool cmp(int a, int b) {
	return dfn[a] < dfn[b];
}
inline void insert(int x) {
	if (top == 1) {s[++top] = x; return ;}
	int lca = query(x, s[top]);
	if (lca == s[top]) return ;//祖先都走不到,它肯定也走不到哈
	while (top > 1 && dfn[s[top-1]] >= dfn[lca]) t[s[top-1]].push_back(s[top]), top--;
	if (lca != s[top]) t[lca].push_back(s[top]), s[top] = lca;
	s[++top] = x;
	return ;
}
LL dp(int u) {
	LL S = 0;
	if (!t[u].size()) return a[u];
	for (int i = 0; i < (int)t[u].size(); i++) {
		int v = t[u][i];
		S += dp(v);
	}
	t[u].clear();
	if (u==1) return S;
	return min(S, 1ll*a[u]);
}
int main() {
	//freopen(".in", "r", stdin);
	//freopen(".out", "w", stdout);
	int n = gi();
	for (int i = 1; i < n; i++) {
		int x = gi(), y = gi(), z = gi();
		add(x, y, z); add(y, x, z);
	}
	a[1] = INF;
	init(1, 0);
	int m = gi();
	while (m--) {
		int k = gi();
		for (int i = 1; i <= k; i++)
			o[i] = gi();
		sort(o+1, o+1+k, cmp);
		s[top = 1] = 1;
		for (int i = 1; i <= k; i++) insert(o[i]);
		for (int i = 1; i < top; i++)
			t[s[i]].push_back(s[i+1]);
		printf("%lld\n", dp(1));
	}
	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)
		
P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...
 - [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处理出虚树上每个点最近的议事处 然后枚举虚树上每一条边,考虑其对两端 ...
 
随机推荐
- 【COCI2012】覆盖字符串
			
[题目描述] 给出一个长度为N的小写字母串,现在Mirko有M个若干长度为Li字符串.现在Mirko要用这M个字符串去覆盖给出的那个字符串的.覆盖时,必须保证:1.Mirko的字符串不能拆开,旋转:2 ...
 - c语言学习笔记 for循环的结构
			
其实感觉for循环没有while循环那么直白好理解. for(i=0;i<n;i++) { dosth(); } i=0是i的初始值. i<n是循环进行的条件. i++是每次循环要做的事情 ...
 - EZOJ #202
			
传送门 分析 我们知道选一个点的代价就是他所有出边边权的异或和 由于一条边如果两个端点均选边权会异或两次变回0,所以不必担心重复的情况 于是直接跑线性基即可 代码 #include<bits/s ...
 - js 简单抽奖实现
			
大家在很多活动页面上都看到绚丽多彩的抽奖运用,网上也有比较多关于这方面的js和用as.今天我在工作的时候也要做个抽奖的运用.我之前没有写过这类的js,也不会as,就得屁颠屁颠的问度娘啦,虽然找到有js ...
 - 简单好用的表单校验插件——jQuery Validate基本使用方法总结
			
jquery validate当前最新版本是1.17.0,下载链接是:https://github.com/jquery-validation/jquery-validation/releases/t ...
 - 微信运动数据抓取(PHP)
			
“微信运动”能够向朋友分享一个包含有运动数据的网页,网页中就有我们需要的数据.url类似于:http://hw.weixin.qq.com/steprank/step/personal?openid= ...
 - sqlserver中 多条数据合并成一条数据 (stuff 与 for xml path 连用)
			
SQL 列转行,即多行合并成一条 需求:按照分组,将多条记录内容合并成一条,效果如下: 数据库示例: CREATE TABLE [t2]([NID] [bigint] NULL,[district ...
 - EventTrigger
			
EventTrigger事件触发器. 相比较数据,属性,事件触发器是XAML的UI层中最重要的一个部分. 事件触发器中,触发的效果是动画,不再是setter. 也是很有意思的 <对象.Style ...
 - iOS开发系统类功能划分
			
0.OC语法基础 CHOCBase Object C语法学习笔记(一) Object C语法学习笔记(二) 1.UI类 自定义控件程序运行流程 setNeedsLayOut和setNeedsDispl ...
 - Agreement has been updated--Edit Phone Number最便捷解决办法(不需要安全提示问题和双重认证)
			
2018年06月04日亲测有效: CSDN博客跳转网址: