bzoj 3611 [Heoi2014]大工程(虚树+DP)
3611: [Heoi2014]大工程
Time Limit: 60 Sec Memory Limit: 512 MB
Submit: 408 Solved: 190
[Submit][Status][Discuss]
Description
Input
第一行 n 表示点数。
Output
输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。
Sample Input
2 1
3 2
4 1
5 2
6 4
7 5
8 6
9 7
10 9
5
2
5 4
2
10 4
2
5 2
2
6 1
2
6 1
Sample Output
6 6 6
1 1 1
2 2 2
2 2 2
HINT
n<=1000000
Source
【思路】
虚树+树上DP
对每次询问构造虚树,在虚树上进行DP。
ans1和ans2即树上的最长/短链问题,利用前缀和思想可以求解。
设sum[x] = ∑(sum[y] + w * size[y]); 则有
ans += ∑((sum[y] + w * size[y]) * (size[x] - size[y]));
其中size[x]表示以x为根的子树包含的询问点数目,w为x->y的边长。
好大的工程=-=
【代码】
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; const int N = +;
const int INF = 1e9+1e9;
const int D = ; typedef long long LL;
vector<int> G[N],g[N];
int d[N],dfn[N];
int n,q,dfsc; void adde(int u,int v) {
if(u!=v) G[u].push_back(v); else return;
}
bool cmp(const int& lhs,const int& rhs) {
return dfn[lhs]<dfn[rhs];
}
////////////////////////////////////////////////////lca which cuts down about 5000ms
int siz[N],top[N],son[N],fa[N];
void dfs1(int u) {
siz[u]=,son[]=; dfn[u]=++dfsc;
for(int i=;i<g[u].size();i++) {
int v=g[u][i];
if(v!=fa[u]) {
fa[v]=u; d[v]=d[u]+;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int tp) {
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(int i=;i<g[u].size();i++) {
int v=g[u][i];
if(v!=son[u] && v!=fa[u]) dfs2(v,v);
}
}
int LCA(int u,int v) {
while(top[u]!=top[v])
if(d[top[u]]>=d[top[v]]) u=fa[top[u]];
else v=fa[top[v]];
return d[u]<d[v]? u:v;
}
////////////////////////////////////////////////
LL sum[N],ans;
int ans1,ans2,mi[N],mx[N],sz[N]; bool ifq[N];
int dp(int u) {
sum[u]=; sz[u]=ifq[u];
mi[u]=ifq[u]? :INF;
mx[u]=ifq[u]? :-INF;
for(int i=;i<G[u].size();i++) {
int v=G[u][i],w=d[v]-d[u];
dp(v);
sz[u]+=sz[v];
sum[u]+=sum[v]+sz[v]*w;
ans1=min(ans1,mi[u]+mi[v]+w);
ans2=max(ans2,mx[u]+mx[v]+w);
mi[u]=min(mi[u],mi[v]+w);
mx[u]=max(mx[u],mx[v]+w);
}
for(int i=;i<G[u].size();i++) {
int v=G[u][i],w=d[v]-d[u];
ans+=(sum[v]+sz[v]*w)*(sz[u]-sz[v]);
}
ifq[u]=; G[u].clear(); //clear
}
void read(int& x) {
char c=getchar();while(!isdigit(c))c=getchar();
x=;while(isdigit(c))x=x*+c-'' , c=getchar();
}
void solve() {
int tot=,top=,k;
static int st[N],h[N];
read(k);
for(int i=;i<=k;i++) read(h[i]),ifq[h[i]]=;
sort(h+,h+k+,cmp);
st[++top]=;
for(int i=;i<=k;i++) {
int p=h[i],lca=LCA(p,st[top]);
for(;;) {
if(d[lca]>=d[st[top-]]) {
adde(lca,st[top]);
top--;
if(st[top]!=lca) st[++top]=lca;
break;
}
adde(st[top-],st[top]); top--;
}
if(st[top]!=p) st[++top]=p;
}
while(--top) adde(st[top],st[top+]);
ans=ans2= , ans1=INF;
dp();
printf("%lld %d %d\n",ans,ans1,ans2);
}
int main() {
read(n);
int u,v;
for(int i=;i<n;i++) {
read(u),read(v);
g[u].push_back(v) , g[v].push_back(u);
}
d[]=; dfs1(); dfs2(,);
read(q);
while(q--) solve();
return ;
}
bzoj 3611 [Heoi2014]大工程(虚树+DP)的更多相关文章
- bzoj 3611[Heoi2014]大工程 虚树+dp
题意: 给一棵树 每次选 k 个关键点,然后在它们两两之间 新建 C(k,2)条 新通道. 求: 1.这些新通道的代价和 2.这些新通道中代价最小的是多少 3.这些新通道中代价最大的是多少 分析:较常 ...
- BZOJ.3611.[HEOI2014]大工程(虚树 树形DP)
题目链接 要求的和.最大值.最小值好像都可以通过O(n)的树形DP做,总询问点数<=2n. 于是建虚树就可以了.具体DP见DP()函数,维护三个值sum[],mx[],mn[]. sum[]要开 ...
- bzoj 3611: [Heoi2014]大工程 虚树
题目: 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 ...
- BZOJ 3611 [Heoi2014]大工程 ——虚树
虚树第二题.... 同BZOJ2286 #include <map> #include <cmath> #include <queue> #include < ...
- bzoj 3611(洛谷 4103) [Heoi2014]大工程——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3611 https://www.luogu.org/problemnew/show/P4103 ...
- luogu P4103 [HEOI2014]大工程 虚树 + 树形 DP
Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通 ...
- 洛谷P4103 [HEOI2014]大工程(虚树 树形dp)
题意 链接 Sol 虚树. 首先建出虚树,然后直接树形dp就行了. 最大最小值直接维护子树内到该节点的最大值,然后合并两棵子树的时候更新一下答案. 任意两点的路径和可以考虑每条边两边的贡献,\(d[x ...
- [HEOI2014][bzoj3611] 大工程 [虚树+dp]
题面: 传送门 思路: 又是一道虚树入门级的题目,但是这道题的实际难点在于dp 首先,这道题是可以点分治做的,而且因为6s时限随便浪,所以写点分治也不是不可以 但是,dp因为$O\left(n\rig ...
- bzoj 3611: [Heoi2014]大工程 && bzoj 2286: [Sdoi2011消耗战
放波建虚树的模板. 大概是用一个栈维护根节点到当前关键点的一条链,把其他深度大于lca的都弹出去. 每次做完记得复原. 还有sort的时候一定要加cmp!!! bzoj 3611 #include&l ...
随机推荐
- easyui实现datagrid数字排序问题
我们在使用easyui对列进行自动排序的时候(即顺序倒序),正常情况下是通过设置field中的sortable:true属性来控制是否可以排序.但是我们会发现一个有趣的问题,在对数字进行排序的时候,这 ...
- iterator迭代器的使用
部分摘自C++ Primer: 所有的标准库容器类都定义了相应的iterator类型,如vector:vector<int>::iterator iter; 这条语句定义了一个名为iter ...
- ACM YTU 《挑战编程》第一章 入门 Problem E: Graphical Editor
Description Graphical editors such as Photoshop allow us to alter bit-mapped images in the same way ...
- jquery之分页插件smartpaginator
今天推荐一个分页工具条插件:Smart Paginator,这个插件用途还是很广的,而且可定制性相当不错,目前内置三种颜色,有需要的话,可以自己改css定制颜色 1.如何使用Smart Paginat ...
- 深入理解QStateMachine与QEventLoop事件循环的联系与区别
最近一直在倒腾事件循环的东西,通过查看Qt源码多少还是有点心得体会,在这里记录下和大家分享.总之,对于QStateMachine状态机本身来说,需要有QEventLoop::exec()的驱动才能支持 ...
- CoffeeScript飞一样的写javascript
之前看到同事在使用coffeescript写js,当我看到那简介的coffee文件,就深深的被coffescript吸引了,简洁的语法,熟练之后会大大提升javascript的开发速度,写脚本也能像飞 ...
- Node.js(window)基础(1)——用cmd命令行访问某一文件夹下的js文件
一.安装,从官网上下载安装,安装基本一直点击下一步就行.注意:node.js基于Python的,安装node.js之前电脑上要安装Python,最好是Python2.7或2.6. 二.cmd进入命令行 ...
- jquery 核心
1.jquery核心函数 1.1 jQuery([selector,[context]]); $("#id"),$(document.body),$(" ...
- OpenCV例程实现人脸检测
前段时间看的OpenCV,其实有很多的例子程序,参考代码值得我们学习,对图像特征提取三大法宝:HOG特征,LBP特征,Haar特征有一定了解后. 对本文中的例子程序刚开始没有调通,今晚上调通了,试了试 ...
- .Net4.0 ashx页面报错:检测到有潜在危险的Request.Form值(转)
原地址:http://zzhi191.blog.163.com/blog/static/1350849520111116518067/ web开发中难免要多到ajax技术. asp.net中我们处理a ...