https://www.lydsy.com/JudgeOnline/problem.php?id=2286

wa了两次因为lca犯了zz错误

这道题如果不多次询问的话就是裸dp。

一棵树上多次询问,且总共询问的点数较小(能够承受得住加个logn的复杂度(常数就不管了,按理说还要*2吧))可以用虚树来处理。

虚树就是对每次询问将有用的点建一棵树,每次询问查询m个点,则这棵树最多m*2个点(太优秀了)。

这个虚树的建立过程是用栈维护一条链,每加入一个点就把她和前一条链的叶子节点的lca和这个点本身加入虚树中,然后将当前链的叶子节点改为当前加入的点。

dfs序是个好东西,它帮助维护了这条链和后面点的关系(的逻辑性?(看到代码就懂了吧,反正就很有逻辑就对了))。

所以我之前为什么要学树链剖分,树链剖分什么用都没有嘤嘤嘤,最喜欢倍增了。(日常抛弃旧爱)

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
#define LL long long
const int maxn=;
const LL minf=(LL)5e17;
int n,m;
struct nod{
int nex,y,v;
};nod e[maxn*];nod e1[maxn*];
int head[maxn]={},tot=;
int head1[maxn]={},tot1=;
int id[maxn]={},cnt=;
int fa[maxn][]={},dep[maxn]={};
LL dis[maxn]={},f[maxn]={};
int a[maxn]={},tly=;
int sta[maxn]={},tai=;
inline int mread(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void init(int x,int y,int v){
e[++tot].y=y;e[tot].v=v;e[tot].nex=head[x];head[x]=tot;
}
inline void init1(int x,int y){
if(x==y)return;
e1[++tot1].y=y;e1[tot1].nex=head1[x];head1[x]=tot1;
}
void dfs(int x,int pa){
fa[x][]=pa;id[x]=++cnt;
for(int i=;fa[fa[x][i-]][i-]!=;++i)fa[x][i]=fa[fa[x][i-]][i-];
for(int i=head[x];i;i=e[i].nex){
int y=e[i].y;
if(y==pa)continue;
dis[y]=dis[x]<e[i].v?dis[x]:e[i].v;
dep[y]=dep[x]+;
dfs(y,x);
}
}
bool mcmp(int x,int y){return id[x]<id[y];}
int getlca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=;i>=;--i){
if(!fa[x][i])continue;
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(dep[x]==dep[y])break;
}
if(x==y)return x;
for(int i=;i>=;--i){
if(!fa[x][i])continue;
if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}
}
return fa[x][];
}
void dfs1(int x){
f[x]=dis[x];LL v=;
for(int i=head1[x];i;i=e1[i].nex){
dfs1(e1[i].y);
v+=f[e1[i].y];
}
if(v)f[x]=min(f[x],v);
head1[x]=;
}
void cutit(){
int q=mread(); for(int i=;i<=q;++i)a[i]=mread();
sort(a+,a++q,mcmp); tly=;
for(int i=;i<=q;++i){if(getlca(a[i],a[tly])!=a[tly])a[++tly]=a[i];}
//由根节点到叶子节点的每条链上至多只有一个点
tai=;sta[]=;tot1=;int lc;
for(int i=;i<=tly;i++){//sta按照dfs序维护了一条链
lc=getlca(sta[tai],a[i]);
for(;tai>;){//更改链向下延伸的方向,把之前方向的点连上
if(dep[sta[tai-]]<=dep[lc]){
init1(lc,sta[tai]);tai--;
if(sta[tai]!=lc)sta[++tai]=lc;
break;
}init1(sta[tai-],sta[tai]);tai--;
}
if(sta[tai]!=a[i])sta[++tai]=a[i];
}
while(--tai)init1(sta[tai],sta[tai+]);
dfs1();
printf("%lld\n",f[]);
}
int main(){
int x,y,v;
n=mread();
for(int i=;i<n;++i){
x=mread();y=mread();v=mread();
init(x,y,v);init(y,x,v);
}
dis[]=minf; dep[]=; dfs(,);
m=mread(); for(int i=;i<=m;++i) cutit();
return ;
}

BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序的更多相关文章

  1. BZOJ.2286.[SDOI2011]消耗战(虚树 树形DP)

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

  2. bzoj 2286: [Sdoi2011]消耗战 虚树+树dp

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一 ...

  3. bzoj 2286 [Sdoi2011]消耗战 虚树+dp

    题目大意:多次给出关键点,求切断边使所有关键点与1断开的最小费用 分析:每次造出虚树,dp[i]表示将i和i子树与父亲断开费用 对于父亲x,儿子y ①y为关键点:\(dp[x]\)+=\(dismn( ...

  4. BZOJ 2286: [Sdoi2011]消耗战 虚树

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

  5. BZOJ2286: [Sdoi2011]消耗战(虚树/树形DP)

    Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5246  Solved: 1978[Submit][Status][Discuss] Descript ...

  6. BZOJ 2286 [Sdoi2011]消耗战 ——虚树

    虚树第一题. 大概就是建一颗只与询问有关的更小的新树,然后在虚树上DP #include <map> #include <ctime> #include <cmath&g ...

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

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

  8. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  9. 【BZOJ】2286: [Sdoi2011]消耗战 虚树+DP

    [题意]给定n个点的带边权树,每次询问给定ki个特殊点,求隔离点1和特殊点的最小代价.n<=250000,Σki<=500000. [算法]虚树+DP [题解]考虑普通树上的dp,设f[x ...

随机推荐

  1. 【译】第四篇 Integration Services:增量加载-Updating Rows

    本篇文章是Integration Services系列的第四篇,详细内容请参考原文. 回顾增量加载记住,在SSIS增量加载有三个使用案例:1.New rows-add rows to the dest ...

  2. angular select ng-change实时获取value

    <select ng-model="vm.selectVal" ng-options="o.id as o.title for o in vm.optionsDat ...

  3. poj1063

    题意:有一些珠子排成一圈,珠子有两种颜色:黑和白.每次操作可以调换中间隔着一个珠子的两珠子的位置,给出这个圈子的初始状态,问最终能否通过操作让圈子中所有同色的珠子排在一起,即黑白分开. 分析:分两种情 ...

  4. css-概述和选择器

    一:CSS 概述 CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素 样式通常存储在样式表中 把样式添加到 HTML 4.0 中,是为了解决内容与 ...

  5. tf.summary.merge_all()

    1.自动管理模式 summary_writer = tf.summary.FileWriter('E:/data/tensorflow-master/1.Cnn_Captcha/result/', f ...

  6. js事件兼容处理

    js封装事件处理函数,兼容ie,支持事件代理 var eventUtil = { bindEvent: function(el, type, target, callback, popgation) ...

  7. 读书笔记--C陷阱与缺陷(三)

    第三章 1. 指针与数组 书中强调C中数组注意的两点: 1)     C语言只有一维数组,但是数组元素可以是任何类型对象,是另外一个数组时就产生了二维数组.数组大小是常数(但GCC实现了变长数组..) ...

  8. python_docx制作word文档

    一.docx模块 Python可以利用python-docx模块处理word文档,处理方式是面向对象的.也就是说python-docx模块会把word文档,文档中的段落.文本.字体等都看做对象,对对象 ...

  9. Oracle学习笔记:ORA-22992 cannot use LOB locators selected from remote tables

    通过DB_LINK访问远程表的时候出现 ORA-22992: cannot use LOB locators selected from remote tables 错误. 原因:因为表中含有clob ...

  10. NSPredicate用法总结(Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取)

    简述:Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取. 定义(最常用到的方法): NSPredicate *ca = [NSPred ...