BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca
BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP
Description
Input
第一行一个整数n,代表岛屿数量。
接下来n-1行,每行三个整数u,v,w,代表u号岛屿和v号岛屿由一条代价为c的桥梁直接相连,保证1<=u,v<=n且1<=c<=100000。
第n+1行,一个整数m,代表敌方机器能使用的次数。
接下来m行,每行一个整数ki,代表第i次后,有ki个岛屿资源丰富,接下来k个整数h1,h2,…hk,表示资源丰富岛屿的编号。
Output
输出有m行,分别代表每次任务的最小代价。
Sample Input
1 5 13
1 9 6
2 1 19
2 4 8
2 3 91
5 6 8
7 5 4
7 8 31
10 7 9
3
2 10 6
4 5 7 8 3
3 9 4 6
Sample Output
32
22
HINT
对于100%的数据,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1
如果询问只有一次,我们可以想出DP做法。
首先将边权下放到点权上,设F[i]表示i的子树中所有资源都被切断的最小代价。
如果i这个点是资源,则f[i]=代价val[i]。
否则f[i]=min(g[i],子树f[to]和)。
但这样每次做是O(n)的。
考虑实际上不是每条边都会用到。
我们先处理出g[x]表示从x到根的最短的代价,用这个代替val[x]显然是可行的。
这样我们就不需要存全部的点。
考虑重新建一棵树,其中包含所有点和他们的lca。
用一个栈来维护一条链,每次保证栈中的是一条链,否则弹栈,弹栈的同时连边。
方法:每次求出当前点和栈顶的lca,一直弹栈直到栈顶的深度小于等于lca的深度。
然后最后对剩余栈中的点连边。栈底元素就是lca中深度最小的一个。DP即可。
注意每次连边后head要清。
代码:
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
inline char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rd() {
int x=0; char ch=nc();
while(ch<'0'||ch>'9') ch=nc();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=nc();
return x;
}
char pbuf[100000],*pp=pbuf;
void push(const char ch) {
if(pp-pbuf==100000) fwrite(pbuf,1,100000,stdout),pp=pbuf;
*pp++=ch;
}
void write(ll x) {
static int sta[50];
int top=0;
do{sta[top++]=x%10,x/=10;}while(x);
while(top)push(sta[--top]+'0');
}
#define N 250050
ll f[N],g[N];
int head[N],to[N<<1],nxt[N<<1],val[N<<1],cnt,n,m;
int dep[N],fa[N],top[N],siz[N],son[N],dfn[N],a[N],h[N],la,S[N],tp,need[N],b[N<<1];
inline void add(int u,int v) {
if(!v) return ;
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
inline bool cmp(int x,int y) {return dfn[x]<dfn[y];}
void dfs1(int x) {
int i; siz[x]=1; dfn[x]=++dfn[0];
for(i=head[x];i;i=nxt[i]) {
if(to[i]!=fa[x]) {
fa[to[i]]=x; dep[to[i]]=dep[x]+1; g[to[i]]=min(g[x],1ll*val[i]);
dfs1(to[i]);
siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[son[x]]) son[x]=to[i];
}
}
}
void dfs2(int x,int t) {
top[x]=t;
if(son[x]) dfs2(son[x],t);
int i;
for(i=head[x];i;i=nxt[i]) {
if(to[i]!=fa[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
}
}
int lca(int x,int y) {
while(top[x]!=top[y]) {
if(dep[top[x]]>dep[top[y]]) swap(x,y);
y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
void DP(int x) {
if(need[x]) {f[x]=g[x]; return ;}
ll sum=0;
int i;
for(i=head[x];i;i=nxt[i]) {
DP(to[i]);
sum+=f[to[i]];
}
f[x]=min(g[x],sum);
}
int main() {
n=rd();
g[1]=1ll<<60;
int i,x,y,z;
for(i=1;i<n;i++) {
x=rd(); y=rd(); z=rd();
add(x,y),val[cnt]=z;
add(y,x),val[cnt]=z;
}dep[1]=1;
dfs1(1); dfs2(1,1); memset(head,0,sizeof(head)); cnt=0;
m=rd();
while(m--) {
la=rd(); b[0]=la;
for(i=1;i<=la;i++) a[i]=rd(),b[i]=a[i],need[a[i]]=1;
sort(a+1,a+la+1,cmp);
tp=0; S[++tp]=a[1];
for(i=2;i<=la;i++) {
int l=lca(a[i],S[tp]),c=0;
while(tp&&dep[S[tp]]>dep[l]) {
if(c) add(S[tp],c);
c=S[tp--];
}
if(S[tp]==l&&c) add(S[tp],c);
if(dep[S[tp]]<dep[l]&&c) add(l,c),S[++tp]=l;
S[++tp]=a[i];
b[++b[0]]=l;
}
while(tp>1) add(S[tp-1],S[tp]),tp--;
// for(i=head[1];i;i=nxt[i]) printf("%d ",to[i]); puts("");
// for(i=head[3];i;i=nxt[i]) printf("%d ",to[i]); puts("");
// for(i=head[5];i;i=nxt[i]) printf("%d ",to[i]); puts("");
// for(i=head[7];i;i=nxt[i]) printf("%d ",to[i]); puts("");
// for(i=head[8];i;i=nxt[i]) printf("%d ",to[i]); puts("");
DP(S[1]);
write(f[S[1]]); push('\n');
for(i=1;i<=b[0];i++) need[b[i]]=head[b[i]]=0;
head[0]=0; cnt=0;
}
fwrite(pbuf,1,pp-pbuf,stdout);
}
/*
10
1 5 13
1 9 6
2 1 19
2 4 8
2 3 91
5 6 8
7 5 4
7 8 31
10 7 9
1
4 5 7 8 3
*/
BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca的更多相关文章
- [bzoj2286][Sdoi2011]消耗战(虚树上的DP)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2286 分析:对于普通的树形dp:f[x]=min(∑f[son],m[x]),其中f[ ...
- 【BZOJ-2286】消耗战 虚树 + 树形DP
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2120 Solved: 752[Submit][Status] ...
- bzoj 2286(虚树+树形dp) 虚树模板
树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5002 Sol ...
- 【BZOJ-3572】世界树 虚树 + 树形DP
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1084 Solved: 611[Submit][Status ...
- BZOJ5341[Ctsc2018]暴力写挂——边分治+虚树+树形DP
题目链接: CSTC2018暴力写挂 题目大意:给出n个点结构不同的两棵树,边有边权(有负权边及0边),要求找到一个点对(a,b)满足dep(a)+dep(b)-dep(lca)-dep'(lca)最 ...
- [WC2018]通道——边分治+虚树+树形DP
题目链接: [WC2018]通道 题目大意:给出三棵n个节点结构不同的树,边有边权,要求找出一个点对(a,b)使三棵树上这两点的路径权值和最大,一条路径权值为路径上所有边的边权和. 我们按照部分分逐个 ...
- BZOJ_2097_[Usaco2010 Dec]Exercise 奶牛健美操_二分答案+树形DP
BZOJ_2097_[Usaco2010 Dec]Exercise 奶牛健美操_二分答案+树形DP Description Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的 ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
- 树形DP+树状数组 HDU 5877 Weak Pair
//树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...
随机推荐
- 【尺取或dp】codeforces C. An impassioned circulation of affection
http://codeforces.com/contest/814/problem/C [题意] 给定一个长度为n的字符串s,一共有q个查询,每个查询给出一个数字m和一个字符ch,你的操作是可以改变字 ...
- 【bzoj1090】 [SCOI2003]字符串折叠
[bzoj1090] [SCOI2003]字符串折叠 2014年3月9日3,1140 Description 折叠的定义如下: 1. 一个字符串可以看成它自身的折叠.记作S S 2. X(S)是X ...
- 2016 Multi-University Training Contest 8 solutions BY 学军中学
1001: 假设有4个红球,初始时从左到右标为1,2,3,4.那么肯定存在一种方案,使得最后结束时红球的顺序没有改变,也是1,2,3,4. 那么就可以把同色球都写成若干个不同色球了.所以现在共有n个颜 ...
- [bzoj3998][TJOI2015]弦论_后缀自动机
弦论 bzoj-3998 TJOI-2015 题目大意:给定一个字符串,求其$k$小子串. 注释:$1\le length \le 5\cdot 10^5$,$1\le k\le 10^9$. 想法: ...
- D. Spongebob and Squares--cf599D(数学)
http://codeforces.com/problemset/problem/599/D 题目大意:给你一个数k 让你求一个n*m的矩形里面包含k个正方形 输出有几个这样的矩形 分别是什么 ...
- 标准格式包含: 私有属性 无参构造 有参构造 setter 和getter 需求中的方法 需求一: 员工类Employee 属性:姓名name,工号id,工资salary 行为:显示所有成员信息的方法show() 需求二: 动物类Animal 属性:姓名name,年龄age 行为:吃饭
// 员工类 public class Employee { private String name; private int id; private double salary; public ...
- 搭建网络svn实战
工作中的问题(7) 转自:http://blog.csdn.net/xiaoting451292510/article/details/8562570 经常性我们和朋友写一些程序,大家在不同的城市确有 ...
- sklearn特征工程总结
转自: http://www.cnblogs.com/jasonfreak/p/5448385.html https://www.zhihu.com/question/28641663/answer/ ...
- 【c++】多重继承与虚继承
派生类的构造函数初始化列表将实参分别传递给每个直接基类,其中基类的构造顺序与派生列表中基类的出现顺序保持一致,而与派生类构造函数初始化列表中基类的顺序无关. 类型转换与多个基类 编译器不会在派生类向基 ...
- ThoughtWorks技术雷达
ThoughtWorks技术雷达 技术成熟方案的一个推荐网站.