bzoj 2286
第一道"虚树"题目(好吧,我也不知道这是不是虚树,但和虚树的思想肯定是一样的,都是简化树结构)
这一类算法核心思想都是简化树结构,只取我们必须的节点和一些信息,然后在简化后的树结构上工作。
首先,如果这道题只有一次询问,那么很容易想到树形DP的解法,但这道题又多组询问,并且限制了所有询问的关键点个数,这意味着我们必须设计出一种算法,她回答一组询问的复杂度只和关键点个数相关(O(k)或O(klogk)都是可接受的),而和原图无关(最多加个logn)。
然后就有了虚树,我们可以构建一个新的树,这棵树上有所有关键点,以及相邻dfs序上相邻的两个关键点的lca,我们发现,这样的图包括了所有关键点的lca以及所有关键点,然后改一下DP就可以在这棵树上快速的搞了(因为节点个数是O(2*k),所以这样DP的复杂度就从O(n)变成了O(k))。
DP:
dp[i]表示将i及其子树中所有关键点与跟节点断开所需的最小代价(可以砍他们上面的边)
构简化图:
对于一个询问,我们先将其关键点按照DFS序排序。然后维护一个栈保存当前走了的关键点或关键点之间的LCA,当我们要插入一个新的关键节点时,我们根据当前节点与当前栈顶节点LCA的深度与栈顶元素的深度来判断是否需要弹出节点,一直弹出,直到深度大于等于栈顶元素(注意,这个LCA是最初的栈顶与新的关键节点的LCA)
/**************************************************************
Problem: 2286
User: idy002
Language: C++
Result: Accepted
Time:6700 ms
Memory:32060 kb
****************************************************************/ #include <cstdio>
#include <vector>
#include <algorithm>
#define min(a,b) ((a)<(b)?(a):(b))
#define oo 0x3f3f3f3f
#define N 250010
#define P 17
using namespace std; typedef long long dnt; int n, m;
int head[N], dest[N+N], wght[N+N], next[N+N], ntot;
int dfn[N], dep[N], bst[N], anc[N][P+], idc;
int qcnt, aa[N], stk[N], top;
dnt dp[N]; void adde( int u, int v, int w ) {
ntot++;
wght[ntot] = w;
dest[ntot] = v;
next[ntot] = head[u];
head[u] = ntot;
}
void dfs( int u ) {
dfn[u] = ++idc;
for( int p=; p<=P; p++ )
anc[u][p] = anc[anc[u][p-]][p-];
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t], w=wght[t];
if( v==anc[u][] ) continue;
anc[v][] = u;
bst[v] = min( bst[u], w );
dep[v] = dep[u]+;
dfs(v);
}
}
bool cmp( int u, int v ) {
return dfn[u]<dfn[v];
}
int lca( int u, int v ) {
if( dep[u]<dep[v] ) swap(u,v);
int t=dep[u]-dep[v];
for( int p=; t; t>>=,p++ )
if( t& ) u=anc[u][p];
if( u==v ) return u;
for( int p=P; p>= && anc[u][]!=anc[v][]; p-- )
if( anc[u][p]!=anc[v][p] )
u=anc[u][p], v=anc[v][p];
return anc[u][];
}
void sov() {
scanf( "%d", &qcnt );
for( int i=; i<=qcnt; i++ )
scanf( "%d", aa+i );
sort( aa+, aa++qcnt, cmp ); stk[top=] = ;
dp[] = ;
for( int i=; i<=qcnt; i++ ) {
int ca=lca(aa[i],stk[top]);
while( dep[stk[top]]>dep[ca] ) {
int fa, u;
u = stk[top];
top--;
if( dep[stk[top]]<=dep[ca] ) {
if( dep[stk[top]]<dep[ca] ) {
stk[++top] = ca;
dp[ca] = ;
}
fa = stk[top]; dp[u] = min( dp[u], bst[u] );
dp[fa] += dp[u];
break;
}
fa = stk[top]; dp[u] = min( dp[u], bst[u] );
dp[fa] += dp[u];
}
int u=aa[i];
stk[++top] = u; dp[u] = bst[u];
}
while( top ) {
if( top- ) {
int fa=stk[top-], u=stk[top]; dp[u] = min( dp[u], bst[u] );
dp[fa] += dp[u];
}
top--;
}
printf( "%lld\n", dp[] );
}
int main() {
scanf( "%d", &n );
for( int i=,u,v,w; i<n; i++ ) {
scanf( "%d%d%d", &u, &v, &w );
adde( u, v, w );
adde( v, u, w );
}
anc[][] = ;
dep[] = ;
bst[] = oo;
dfs();
scanf( "%d", &m );
for( int i=; i<=m; i++ )
sov();
}
bzoj 2286的更多相关文章
- BZOJ 2286: [Sdoi2011]消耗战
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2082 Solved: 736[Submit][Status] ...
- bzoj 2286 [Sdoi2011]消耗战(虚树+树上DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题意] 给定一棵树,切断一条树边代价为ci,有m个询问,每次问使得1号点与查询 ...
- bzoj 2286: [Sdoi2011]消耗战 虚树+树dp
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一 ...
- bzoj 2286(洛谷 2495) [Sdoi2011]消耗战——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2286 https://www.luogu.org/problemnew/show/P2495 ...
- bzoj 3611: [Heoi2014]大工程 && bzoj 2286: [Sdoi2011消耗战
放波建虚树的模板. 大概是用一个栈维护根节点到当前关键点的一条链,把其他深度大于lca的都弹出去. 每次做完记得复原. 还有sort的时候一定要加cmp!!! bzoj 3611 #include&l ...
- BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序
https://www.lydsy.com/JudgeOnline/problem.php?id=2286 wa了两次因为lca犯了zz错误 这道题如果不多次询问的话就是裸dp. 一棵树上多次询问,且 ...
- BZOJ.2286.[SDOI2011]消耗战(虚树 树形DP)
题目链接 BZOJ 洛谷P2495 树形DP,对于每棵子树要么逐个删除其中要删除的边,要么直接断连向父节点的边. 如果当前点需要删除,那么直接断不需要再管子树. 复杂度O(m*n). 对于两个要删除的 ...
- Bzoj 2286 & Luogu P2495 消耗战(LCA+虚树+欧拉序)
题面 洛谷 Bzoj 题解 很容易想到$O(nk)$的树形$dp$吧,设$f[i]$表示处理完这$i$颗子树的最小花费,同时再设一个$mi[i]$表示$i$到根节点$1$路径上的距离最小值.于是有: ...
- bzoj 2286(虚树+树形dp) 虚树模板
树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5002 Sol ...
随机推荐
- CSS实现箭头效果
有时候网页中使用箭头以增强效果,一般的做法是使用图片,今天我们使用CSSCSS来实现“箭头效果”,使用CSS我们必须兼容所有浏览器(IE6.7.8.9.10.+),Chrome,Firefox,Ope ...
- thinkphp博客项目纪录
项目地址:http://files.cnblogs.com/files/wordblog/blog.zip
- 二进制、十进制、十六进制(python)
int(“x”,base=2/8/16)是把x都转换成十进制 二进制: 1111=1*2的3次方+1*2的2次方+1*2的1次方+1*2的0次方 =8+4+2+1=15 1000=1*2的3次方+0 ...
- 记一次powershell反混淆(2)
样本地址 https://www.hybrid-analysis.com/sample/4b4b8b13c264c8f7d7034060e0e4818a573bebc576a94d7b13b4c174 ...
- iTextSharp操作pdf之pdfCreater
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- Freemaker 自定义指令和函数
自定义函数和指令都可以在前台或者后台进行指定. 个人理解:指令的作用,主要是进行页面调整之后进行输出:函数的作用,主要是为了进行运算,返回运算结果供前台展示. (一) 自定义指令 使用以下格式调用自定 ...
- [转载]FFmpeg完美入门[3] - FFmpeg功能及使用说明
1 ffplay对多媒体的支持能力验证 一.视频3gp 177X144 支持播放,在windows下播放正常,但是在linux下面偶有BUG 如果发现画面无法显示而声音可以播放的情况下可以试着切换全屏 ...
- C语言使用数学库编译不通过问题
#include <stdio.h>#include <math.h> int main(){ double a = 10.0,b = 3.0; f ...
- HDU 1043 Eight(反向BFS+打表+康托展开)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...
- LightOJ 1414 February 29(闰年统计+容斥原理)
题目链接:https://vjudge.net/contest/28079#problem/R 题目大意:给你分别给你两个日期(第二个日期大于等于第一个日期),闰年的2月29日称为闰日,让你求两个日期 ...