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. Eureka简介

    Eureka是Spring Cloud Netfix 的一个子模块,也是核心模块之一,用于云端服务发现.一个基于RestFul的服务,用于定位服务,以实现云端中间层服务发现和中间层转移. 服务注册与发 ...

  2. XSS报警机制(前端防火墙:第二篇)

    XSS报警机制(前端防火墙:第二篇) 在第一章结尾的时候我就已经说了,这一章将会更详细的介绍前端防火墙的报警机制及代码.在一章出来后,有人会问为什么不直接防御,而是不防御报警呢.很简单,因为防御的话, ...

  3. JDK1.8源码LinkedList

    引用博文链接 : https://www.cnblogs.com/leskang/p/6029780.html LinkedList继承了 AbstractSequentialList抽象类,而不是像 ...

  4. 用C代码简要模拟实现一下RPC(远程过程调用)并谈谈它在代码调测中的重要应用【转】

    转自:http://blog.csdn.net/stpeace/article/details/44947925 版权声明:本文为博主原创文章,转载时请务必注明本文地址, 禁止用于任何商业用途, 否则 ...

  5. sleep允许休眠, delay不允许

    在Linux Driver开发中,经常要用到延迟函数:msleep,mdelay/udelay. 虽然msleep和mdelay都有延迟的作用,但他们是有区别的. 1.)对于模块本身 mdelay是忙 ...

  6. 全面了解Nginx主要应用场景【转】

    前言 本文只针对 Nginx 在不加载第三方模块的情况能处理哪些事情,由于第三方模块太多所以也介绍不完,当然本文本身也可能介绍的不完整,毕竟只是我个人使用过和了解到过得.所以还请见谅,同时欢迎留言交流 ...

  7. [USACO16OPEN]262144

    传送门啦 其实大家可以先看一下这个题 [USACO16OPEN]248 分析: 数据范围很奇特:n特别,a[i]特别——如果O(N^3)能接受就直接区间DP水过了,但是不行,于是考虑设计一个状态囊括a ...

  8. [android]Intent跳转新的Activity可以传递数据过去

    两种方式: 一,直接通过Bundle对象来传递: 如果我们想要给“收件人”Activity说点什么的话,那么可以通过下面这封“E-mail”来将我们的消息传递出去 Intent intent=new ...

  9. **汇总CodeIgniter(CI)的数据库操作函数

    //查询: $query = $this->db_query("SELECT * FROM table"); ================================ ...

  10. SSIS 学习之旅 FTP文件传输-脚本任务

    这一章主要讲解一下用脚本怎么把CSV文件抛送到FTP服务器上 设计:   通过Demon库的Users表数据生成CSV文件.   生成后的CSV文件抛送到FTP指定目录下. 控件的使用这里就不做详细讲 ...