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

考虑树形DP,我们令mn[i]表示i节点无法与1节点相连切除的最小权值。
显然有mn[i]=min(E(fa,i),mn[fa]).
大致就是i到1的简单路径上的最小边。
我们对于每个询问。把询问的点不妨称为关键点。
令dp[i]表示i节点不能与子树的关键点连接切掉的最小权值。
那么有,如果son[i]是关键点,则dp[i]+=E(i,son(i)).
如果son[i]不是关键点,则dp[i]+=min(dp[son(i)],E(i,son(i))).

考虑最坏每次只询问一个点,则复杂度为O(n*sigma(ki)).显然无法承受。

我们观察到sigma(ki)有限制,这启发了我们构造一颗新树,这棵树称为虚树。
我们把每个节点和每对节点的lca单独拉出来模仿原来的树的形态构造一颗虚树。
这样再在这颗新树上进行树形DP。

构造这棵树的核心思想是每次维护一条最右边的链。
首先把关键点按dfs序排序。
然后相邻的点取lca。
再单调栈维护一下最右边的链就ok啦。

# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <math.h>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define MAXN
# define eps 1e-
# define MAXM
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
typedef long long LL;
typedef unsigned long long ULL;
int _MAX(int a, int b){return a>b?a:b;}
int _MIN(int a, int b){return a>b?b:a;}
int Scan() {
int res=, flag=;
char ch;
if((ch=getchar())=='-') flag=;
else if(ch>=''&&ch<='') res=ch-'';
while((ch=getchar())>=''&&ch<='') res=res*+(ch-'');
return flag?-res:res;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
} struct Edge{int p, next, w;}edge[MAXN<<];
int head[MAXN], cnt=, bin[], ind;
int id[MAXN], dep[MAXN], fa[MAXN][], h[MAXN], st[MAXN], top;
LL ans[MAXN], dp[MAXN]; void add_edge(int u, int v, int w)
{
if (u==v) return ;
edge[cnt].p=v; edge[cnt].next=head[u]; edge[cnt].w=w; head[u]=cnt++;
}
void bin_init(){bin[]=; FO(i,,) bin[i]=bin[i-]<<;}
bool comp(int a, int b){return id[a]<id[b];}
void dfs(int x, int fat)
{
id[x]=++ind;
fa[x][]=fat;
for (int i=; bin[i]<=dep[x]; ++i) fa[x][i]=fa[fa[x][i-]][i-];
for (int i=head[x]; i; i=edge[i].next) {
int v=edge[i].p;
if (v==fat) continue;
dep[v]=dep[x]+;
ans[v]=min(ans[x],(LL)edge[i].w);
dfs(v,x);
}
}
int lca(int x, int y)
{
if (dep[x]<dep[y]) swap(x,y);
int t=dep[x]-dep[y];
for (int i=; bin[i]<=t; ++i) if (bin[i]&t) x=fa[x][i];
for (int i=; i>=; --i) if (fa[x][i]!=fa[y][i]) x=fa[x][i], y=fa[y][i];
if (x==y) return x;
else return fa[x][];
}
void dp_dfs(int x)
{
dp[x]=ans[x];
LL temp=;
for (int i=head[x]; i; i=edge[i].next) {
int v=edge[i].p;
dp_dfs(v);
temp+=dp[v];
}
head[x]=;
if (temp) dp[x]=min(dp[x],temp);
}
void sol()
{
int k, tot=;
cnt=;
scanf("%d",&k);
FOR(i,,k) h[i]=Scan();
sort(h+,h+k+,comp);
h[++tot]=h[];
FOR(i,,k) if (lca(h[tot],h[i])!=h[tot]) h[++tot]=h[i];
st[++top]=;
FOR(i,,tot) {
int f=lca(h[i],st[top]);
while (dep[f]<dep[st[top-]]) add_edge(st[top-],st[top],), top--;
add_edge(f,st[top--],);
if (f!=st[top]) st[++top]=f;
st[++top]=h[i];
}
while (top>) add_edge(st[top-],st[top],), top--;
dp_dfs();
printf("%lld\n",dp[]);
}
int main()
{
int n, m, u, v, w;
bin_init();
n=Scan();
FO(i,,n) u=Scan(), v=Scan(), w=Scan(), add_edge(u,v,w), add_edge(v,u,w);
ans[]=(LL)<<; dfs(,);
m=Scan();
mem(head,);
while (m--) sol();
return ;
}

BZOJ 2286 消耗战 (虚树+树形DP)的更多相关文章

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

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

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

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

  3. BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序

    https://www.lydsy.com/JudgeOnline/problem.php?id=2286 wa了两次因为lca犯了zz错误 这道题如果不多次询问的话就是裸dp. 一棵树上多次询问,且 ...

  4. BZOJ 2286 消耗战 - 虚树 + 树型dp

    传送门 题目大意: 每次给出k个特殊点,回答将这些特殊点与根节点断开至少需要多少代价. 题目分析: 虚树入门 + 树型dp: 刚刚学习完虚树(好文),就来这道入门题签个到. 虚树就是将树中的一些关键点 ...

  5. 【BZOJ2286】【SDOI2011】消耗战 [虚树][树形DP]

    消耗战 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一场战争中,战场由n个岛屿和n-1 ...

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

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

  7. bzoj 2286(虚树+树形dp) 虚树模板

    树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5002  Sol ...

  8. BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca

    BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...

  9. 【BZOJ-3572】世界树 虚树 + 树形DP

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1084  Solved: 611[Submit][Status ...

随机推荐

  1. 爬虫的入门以及scrapy

    一.简介 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟 ...

  2. iOS中延时执行的几种方式的比较和汇总

    本文列举了四种延时执行某函数的方法及其一些区别.假如延时1秒时间执行下面的方法. - (void)delayMethod { NSLog(@"execute"); } 1.perf ...

  3. SharePoint 2013 图文开发系列之网站栏

    网站栏的本质,就是一个xml的描述文件,所以创建过程,基本就是通过Feature部署一个Xml文件,然后修改Xml文件的网站栏描述. 1.添加新项目,选择SharePoint 2013 空项目,如下图 ...

  4. iOS开发中的http浅析

      至于为什么要进行HTTP请求我就不说了.本文主要对HTTP协议做了一些介绍,主要针对网络编程和面试. 先从流程开始说起 APP <---> 服务器 <---> 后台​ 1) ...

  5. iOS 杂笔-25(不要用copy修饰NSMutableString)

    iOS 杂笔-25(不要用copy修饰NSMutableString) 首先对题目进行简单的解释,我所说的不要用copy修饰NSMutableString不是说完全不可以用.但是要清楚一点,既然使用N ...

  6. iOS开发之功能模块--模糊效果

    1.先介绍一个好用的实现模糊效果的框架:https://github.com/YouXianMing/UIImageBlur 2.iOS8 中 UIVisualEffectView 模糊效果的使用 , ...

  7. 11-C语言指针&一维数组&字符串

    一.用指针遍历数组元素 1.最普通的遍历方式是用数组下标来遍历元素 1 // 定义一个int类型的数组 2 int a[4] = {1, 2, 3, 4}; 3 4 int i; 5 for (i = ...

  8. CSS background-color 、image 背景图片

    背景颜色 background-color 语法: background-color:<color> 默认值:transparent  透明 适用于:所有元素 继承性:无 动画性:是 计算 ...

  9. SQL Server 使用OPENROWSET访问ORACLE遇到的各种坑总结

    在SQL Server中使用OPENROWSET访问ORACLE数据库时,你可能会遇到各种坑,下面一一梳理一下你会遇到的一些坑. 1:数据库没有开启"Ad Hoc Distributed Q ...

  10. dom4j读取某个元素的某个属性

    一.dom4j介绍 dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点, ...