【[HEOI2014]大工程 】
可能是虚树板子题了
首先先把虚树建出来,但是这里和那道虚树的入门题不一样,这里所有的询问点都得在虚树里,所以不会存在那种直接不如栈的点
之后我们考虑一下这个三个要求的东西
第一个操作我们需要统计虚树上每一条边的贡献,即被多少个点对经过,根据乘法原理显然有\((t-sz[x])\times sz[x]\times w\)的贡献
第二个操作是最大的距离,这不就是直径吗,子树内部最长链和次长链拼一下就好了
第三个操作是所有点对之间的最小值,因为虚树上有一些点并不是被询问的点,所以不能直接从虚树上选择最小的边,还是需要\(dp\)一下
我们用\(g[x]\)表示\(x\)子树内部的距离\(x\)最近的标记过得点到\(x\)的距离,如果\(x\)被标记了,那么就在这次\(dfs\)之后把其变成\(0\),之后像直径那样合并就好了
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define re register
#define LL long long
#define maxn 1000005
#define INF 99999999999
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
re char c=getchar();int x=0;
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int n,m,num,__,t,top;
LL ans,tot,cnt=INF;
int head[maxn],head_[maxn],a[maxn],st[maxn];
int Top[maxn],fa[maxn],sum[maxn],deep[maxn],son[maxn],dfn[maxn];
LL sz[maxn],dp[maxn],f[maxn],to[maxn],g[maxn],to_[maxn];
struct E {int v,nxt;}e[maxn<<1];
struct Eg {int v,nxt,w;}e_[maxn<<1];
inline int cmp(int x,int y){return dfn[x]<dfn[y];}
inline void add_edge(int x,int y){e[++num].v=y,e[num].nxt=head[x],head[x]=num;}
inline void add(int x,int y,int z){e_[++num].v=y,e_[num].nxt=head_[x],e_[num].w=z,head_[x]=num;}
void dfs1(int x)
{
sum[x]=1;
int maxx=-1;
for(re int i=head[x];i;i=e[i].nxt)
if(!deep[e[i].v])
{
deep[e[i].v]=deep[x]+1,fa[e[i].v]=x;
dfs1(e[i].v);
sum[x]+=sum[e[i].v];
if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v;
}
}
void dfs2(int x,int topf)
{
Top[x]=topf,dfn[x]=++__;
if(!son[x]) return;
dfs2(son[x],topf);
for(re int i=head[x];i;i=e[i].nxt) if(!Top[e[i].v]) dfs2(e[i].v,e[i].v);
}
inline int LCA(int x,int y)
{
while(Top[x]!=Top[y]){if(deep[Top[x]]<deep[Top[y]]) std::swap(x,y);x=fa[Top[x]];}
if(deep[x]<deep[y]) return x;return y;
}
inline void ins(int x)
{
if(top==1){st[++top]=x;return;}
int lca=LCA(x,st[top]);
while(top>1&&dfn[st[top-1]]>=dfn[lca])
add(st[top-1],st[top],deep[st[top]]-deep[st[top-1]]),top--;
if(lca!=st[top]) add(lca,st[top],deep[st[top]]-deep[lca]),st[top]=lca;
st[++top]=x;
}
void Dfs(int x)
{
for(re int i=head_[x];i;i=e_[i].nxt)
if(deep[e_[i].v]>deep[x])
{
Dfs(e_[i].v);
sz[x]+=sz[e_[i].v];
tot+=sz[e_[i].v]*((LL)t-sz[e_[i].v])*(LL)e_[i].w;
if(dp[x]<dp[e_[i].v]+e_[i].w) dp[x]=dp[e_[i].v]+e_[i].w,to[x]=e_[i].v;
if(g[x]>g[e_[i].v]+e_[i].w) g[x]=g[e_[i].v]+e_[i].w,to_[x]=e_[i].v;
}
ans=max(ans,dp[x]);
if(f[x]) cnt=min(cnt,g[x]);
for(re int i=head_[x];i;i=e_[i].nxt)
if(deep[e_[i].v]>deep[x]&&to[x]!=e_[i].v) ans=max(ans,dp[x]+dp[e_[i].v]+(LL)e_[i].w);
for(re int i=head_[x];i;i=e_[i].nxt)
if(deep[e_[i].v]>deep[x]&&to_[x]!=e_[i].v) cnt=min(cnt,g[x]+g[e_[i].v]+(LL)e_[i].w);
if(f[x]) g[x]=0;
}
void clear(int x)
{
sz[x]=0;dp[x]=0,to[x]=0;f[x]=0;g[x]=INF;to_[x]=0;
for(re int i=head_[x];i;i=e_[i].nxt)
if(deep[e_[i].v]>deep[x]) clear(e_[i].v);
head_[x]=0;
}
int main()
{
n=read();
int x,y;
for(re int i=1;i<n;i++) {x=read(),y=read();add_edge(x,y),add_edge(y,x);g[i]=INF;}g[n]=INF;
deep[1]=1,dfs1(1),dfs2(1,1);
m=read();
while(m--)
{
t=read();num=0;ans=0;tot=0;cnt=INF;
for(re int i=1;i<=t;i++) a[i]=read(),sz[a[i]]++,f[a[i]]=1;
std::sort(a+1,a+t+1,cmp);top=0;
int root=LCA(a[1],a[2]);
for(re int i=3;i<=t;i++) root=LCA(root,a[i]);
st[++top]=root;
for(re int i=1;i<=t;i++) if(root!=a[i]) ins(a[i]);
while(top) add(st[top-1],st[top],deep[st[top]]-deep[st[top-1]]),top--;
Dfs(root);
printf("%lld %lld %lld\n",tot,cnt,ans);
clear(root);
}
return 0;
}
【[HEOI2014]大工程 】的更多相关文章
- bzoj 3611: [Heoi2014]大工程 虚树
题目: 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 ...
- luogu P4103 [HEOI2014]大工程 虚树 + 树形 DP
Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通 ...
- 洛谷P4103 [HEOI2014]大工程(虚树 树形dp)
题意 链接 Sol 虚树. 首先建出虚树,然后直接树形dp就行了. 最大最小值直接维护子树内到该节点的最大值,然后合并两棵子树的时候更新一下答案. 任意两点的路径和可以考虑每条边两边的贡献,\(d[x ...
- bzoj 3611(洛谷 4103) [Heoi2014]大工程——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3611 https://www.luogu.org/problemnew/show/P4103 ...
- BZOJ.3611.[HEOI2014]大工程(虚树 树形DP)
题目链接 要求的和.最大值.最小值好像都可以通过O(n)的树形DP做,总询问点数<=2n. 于是建虚树就可以了.具体DP见DP()函数,维护三个值sum[],mx[],mn[]. sum[]要开 ...
- BZOJ 3611 [Heoi2014]大工程 ——虚树
虚树第二题.... 同BZOJ2286 #include <map> #include <cmath> #include <queue> #include < ...
- bzoj 3611[Heoi2014]大工程 虚树+dp
题意: 给一棵树 每次选 k 个关键点,然后在它们两两之间 新建 C(k,2)条 新通道. 求: 1.这些新通道的代价和 2.这些新通道中代价最小的是多少 3.这些新通道中代价最大的是多少 分析:较常 ...
- 【HEOI2014】大工程<虚树>
虚树 我们每天都用心思索着,这究竟是为了什么呢?我想我也不知道,只是觉得如果人不思考问题就很无聊. 我觉得虚树不是什么数据结构,就是一种技巧或者工具.它能把树中\(k\)个关键点以\(O(klogk) ...
- [HEOI2014][bzoj3611] 大工程 [虚树+dp]
题面: 传送门 思路: 又是一道虚树入门级的题目,但是这道题的实际难点在于dp 首先,这道题是可以点分治做的,而且因为6s时限随便浪,所以写点分治也不是不可以 但是,dp因为$O\left(n\rig ...
- bzoj 3611 [Heoi2014]大工程(虚树+DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 408 Solved: 190[Submit][Status] ...
随机推荐
- Html与Css关联到一起
在HTML文件中使用Link标签连接独立的Css文件 将Link标签放在head标签中 like标签是空标签,只写开始标签,不写结束标签 我们需要为like标签设置一些属性 type的值设置为text ...
- Ajax 之XMLHttpRequest讲解
一直以来都听别人说Ajax,今天终于接触到了.......... 一.什么是Ajax? 答: AJAX即“Asynchronous Javascript And XML”(异步JavaScript和X ...
- MyEclipse中设置开发项目时使用的默认JDK
安装好MyEclipse之后,在MyEclipse中开发项目时,默认使用的是MyEclipse是自带的JDK,如下图所示: 如果我们需要使用自己安装好的JDK,那么就需要在MyEclipse中重新设置 ...
- RabbitMq、ActiveMq、ZeroMq、kafka各个消息中间件之间的区别
MQ框架非常之多,比较流行的有RabbitMq.ActiveMq.ZeroMq.kafka.这几种MQ到底应该选择哪个?要根据自己项目的业务场景和需求. 第一部分:RabbitMQ,ActiveMq, ...
- JSTL总结摘要
一 概述 1.什么是JSTL? JSP Standard Taglib,一个定义了一系列标签的标签库,以取代在JSP页面中嵌套的java代码,经常与EL结合使用,使页面风格统一,维护方便. JSTL标 ...
- Java设计模式—桥梁模式
终于又碰到了一个简单点的模式了. 桥梁模式也叫做桥接模式,定义如下: 将抽象和实现解耦,使得两者可以独立地变化. 这句话也太难理解了,桥梁模式是为了解决类继承的缺点而设计 ...
- js 判断 复选框全选、全不选、反选、必选一个
一个挺 使用的 js 代码片段, 判断 复选框全选.全不选.反选.必选一个 记录下, 搬来的 思路: 修改数据的 选中与否状态, 拿到所有的输入框,看是否有选中的状态 <html> & ...
- Android 编辑框插入表情图片
首先,把整理好的表情图片以及布局用到的一些图片导入到项目的res/drawable目录中. 然后,编辑res/layout目录下布局.xml文件,这里我把oschina客户端的布局代码贴上来,供大家参 ...
- EF6 按条件更新多行记录的值
using (var db = new MyDbContext()) { string fromUser = ""; //sender string toUser = " ...
- Anjular中的路由配置以及服务等模块的一些基本操作
1.路由的配置: 在Angular.js中,我们可以根据自己的需求来配置路由,以达到当url中的地址改变时,会跳转不同的页面 <script> //一开始的url:"http:/ ...