bzoj 3611[Heoi2014]大工程 虚树+dp
题意:
给一棵树
每次选 k 个关键点,然后在它们两两之间 新建 C(k,2)条 新通道。
求:
1.这些新通道的代价和
2.这些新通道中代价最小的是多少
3.这些新通道中代价最大的是多少
分析:较常见的dp,详见代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
const int M=1000007;
using namespace std;
typedef long long LL;
const int INF=2147483647;
inline int rd(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
}
int n,m;
int que[M];
int kd[M];
int dep[M];
int dfn[M],tdfn;
int ln[M<<1];
int a[M<<1][23],T;
int pos[M];
int g[M],te,hd[M],td;
struct edge{int y,next;}e[M<<1],dw[M];
void addedge(int x,int y){
e[++te].y=y;e[te].next=g[x];g[x]=te;
}
void addlink(int x,int y){
if(x==y) return;
dw[++td].y=y;dw[td].next=hd[x];hd[x]=td;
}
int st[M],tot;
bool cmp(int x,int y){return dfn[x]<dfn[y];}
LL sz[M],sum[M];
int mx[M],mn[M];
LL ans;
int ansmn,ansmx;
void dfs(int x,int fa){
a[pos[x]=++T][0]=x;
dfn[x]=++tdfn;
int p,y;
for(p=g[x];p;p=e[p].next)
if((y=e[p].y)!=fa){
dep[y]=dep[x]+1;
dfs(y,x);
a[++T][0]=x;
}
}
int gmn(int x,int y){return dep[x]<dep[y]?x:y;}
int LCA(int x,int y){
x=pos[x],y=pos[y];
if(x>y) swap(x,y);
int l=ln[y-x+1];
return gmn(a[x][l],a[y-(1<<l)+1][l]);
}
void init(){
int i,j,l;
for(i=2;i<=T;i++) ln[i]=ln[i>>1]+1;
for(i=T;i>0;i--){
l=ln[T-i+1];
for(j=1;j<=l;j++) a[i][j]=gmn(a[i][j-1],a[i+(1<<j-1)][j-1]);
}
}
int vbuild(int z){
int rt;
int i,x,anc;
sort(que+1,que+z+1,cmp);
rt=que[1];
for(i=1;i<z;i++){
x=LCA(que[i],que[i+1]);
hd[x]=0; kd[x]=2; sz[x]=0; sum[x]=0; mn[x]=INF; mx[x]=-INF;
if(dep[x]<dep[rt]) rt=x;
}
for(i=1;i<=z;i++){
x=que[i];
hd[x]=0; kd[x]=1; sz[x]=0; sum[x]=0; mn[x]=INF; mx[x]=-INF;
}
td=tot=0;
st[++tot]=rt;
for(i=1;i<=z;i++){
x=que[i];
anc=LCA(x,st[tot]);
if(anc==st[tot]) st[++tot]=x;
else{
while( tot>1 && dep[anc]<=dep[st[tot-1]]){
addlink(st[tot-1],st[tot]);
tot--;
}
addlink(anc,st[tot]);
st[tot]=anc;
st[++tot]=x;
}
}
for(i=1;i<tot;i++) addlink(st[i],st[i+1]);
return rt;
}
void dp(int x){
if(kd[x]==1) mn[x]=mx[x]=0,sz[x]=1;//****
int p,y;
LL d;
for(p=hd[x];p;p=dw[p].next){
y=dw[p].y;
d=dep[y]-dep[x];
dp(y);
//能下面这样算就不要求最大次大,总的减子树这样复杂的东西
ans+=sz[y]*sum[x];
ans+=sz[x]*sum[y];
ans+=sz[x]*sz[y]*d;
if(mn[x]!=INF) ansmn=min(ansmn,mn[x]+mn[y]+(int)d);//注意越界
if(mx[x]!=-INF) ansmx=max(ansmx,mx[x]+mx[y]+(int)d);
sz[x]+=sz[y];
sum[x]+=sum[y]+sz[y]*d;
mn[x]=min(mn[x],mn[y]+(int)d);
mx[x]=max(mx[x],mx[y]+(int)d);
}
}
int main(){
freopen("a.txt","r",stdin);
int i,x,y,z;
n=rd();
for(i=1;i<n;i++){
x=rd(),y=rd();
addedge(x,y);
addedge(y,x);
}
x=rand()%n+1;
dep[x]=0;
dfs(x,0);
init();
m=rd();
while(m--){
z=rd();
for(i=1;i<=z;i++) que[i]=rd();
x=vbuild(z);
ans=0;
ansmn=INF;
ansmx=-INF;
dp(x);
printf("%lld %d %d\n",ans,ansmn,ansmx);
}
return 0;
}
bzoj 3611[Heoi2014]大工程 虚树+dp的更多相关文章
- 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 [Heoi2014]大工程(虚树+DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 408 Solved: 190[Submit][Status] ...
- 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 ...
随机推荐
- Ubuntu防火墙ufw安装配置
ubuntu 系统默认已安装ufw. 1.安装sudo apt-get install ufw2.启用sudo ufw enablesudo ufw default deny运行以上两条命令后,开启了 ...
- zf-监察系统的左侧菜单树的表
Sys_Right 这个表
- ajax编程**
ajax 编程 *step1获得 XmlHttpRequest 对象.该对象由浏览器提供,但是该类型并没有标准化.ie 和其它浏览器不同,其它浏览器都支持该类型,而 ie 不支持. function ...
- Chapter 1 First Sight——4
Charlie gave me an awkward, one-armed hug when I stumbled my way off the plane. 当我让我蹒跚的从飞机上下来,查理斯单手给 ...
- CodeForces 609A USB Flash Drives
水题 #include<cstdio> #include<cmath> #include<algorithm> using namespace std; +; in ...
- 使用PHPmailer 发送邮件,使用QQ smtp服务器
<meta charset="utf-8"> <?php include("class.phpmailer.php"); include(&q ...
- 将一个字典内的内value转换为集合:返回一个数组,此数组中包含输入字典的键值对中的数组的所有元素(为NSArray添加category)
- (NSArray *)testa:(NSDictionary *)dic { NSMutableArray *arr_M = [NSMutableArray array]; // 1.遍历每一个元 ...
- Python正则表达式学习笔记
[] 字符类,只要匹配里面的任意字符,都算匹配 . 元字符,可以匹配除换行符之外的所有字符 大小写敏感,但是可以关闭 \d 可以匹配0-9中的任意数字 {3}大括号里面的数字,边上前面一个字符匹配的 ...
- 25个Linux性能监控工具
一段时间以来,我们在网上向读者介绍了如何为Linux以及类Linux操作系统配置多种不同的性能监控工具.在这篇文章中我们将罗列一系列使用最频繁的性能监控工具,并对介绍到的每一个工具提供了相应的简介链接 ...
- Android高斯模糊技术,实现毛玻璃效果(转)
本博客转自郭霖公众号:http://mp.weixin.qq.com/s?__biz=MzA5MzI3NjE2MA==&mid=2650235930&idx=1&sn=e328 ...