题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3611

   https://www.luogu.org/problemnew/show/P4103

虚树的边权就是两端点的 dep 差。

求最短边可以像求最长边一样记录一个 d2[ cr ] 表示 cr 到其子树里最近的关键点的距离。

可以用 vis[ ] 记录哪些点是关键点。在 DP 的 dfs 里清空数组真是舒服。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
const int N=1e6+,K=;
int n,hd[N],xnt,to[N<<],nxt[N<<];
int dep[N],dfn[N],tim,bin[K],pre[N][K];
bool cmp(int x,int y){return dfn[x]<dfn[y];}
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void dfs(int cr,int fa)
{
dfn[cr]=++tim;
dep[cr]=dep[fa]+; pre[cr][]=fa;
for(int t=;bin[t]<=dep[cr];t++)
pre[cr][t]=pre[pre[cr][t-]][t-];
for(int i=hd[cr],v;i;i=nxt[i])
if((v=to[i])!=fa) dfs(v,cr);
}
int get_lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int d=dep[x]-dep[y];
for(int t=;bin[t]<=d;t++)
if(d&bin[t])x=pre[x][t];
if(x==y)return x;
for(int t=;t>=;t--)
if(pre[x][t]!=pre[y][t])
x=pre[x][t],y=pre[y][t];
return pre[x][];
}
namespace Tr{
int hd[N],xnt,to[N],nxt[N],len,mn; ll sm;
int p[N],tot,sta[N],top,siz[N],dis[N],d2[N];
bool vis[N];
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void dfs(int cr)
{
dis[cr]=; siz[cr]=vis[cr]; d2[cr]=(vis[cr]?:N);
for(int i=hd[cr],v;i;i=nxt[i])
{
dfs(v=to[i]); int w=dep[v]-dep[cr];
sm+=(ll)w*siz[v]*(tot-siz[v]);
len=Mx(len,dis[cr]+dis[v]+w); dis[cr]=Mx(dis[cr],dis[v]+w);
mn=Mn(mn,d2[cr]+d2[v]+w); d2[cr]=Mn(d2[cr],d2[v]+w);
siz[cr]+=siz[v];
}
vis[cr]=; hd[cr]=;
}
void solve()
{
tot=rdn(); xnt=;//xnt
for(int i=;i<=tot;i++)p[i]=rdn(),vis[p[i]]=;
sort(p+,p+tot+,cmp); sta[top=]=p[];//cmp!!!
for(int i=;i<=tot;i++)
{
int u=p[i], lca=get_lca(u,sta[top]);
while(top&&dfn[lca]<dfn[sta[top]])
{
if(dfn[sta[top-]]<dfn[lca])
add(lca,sta[top]);
else add(sta[top-],sta[top]);
top--;
}
if(sta[top]!=lca)sta[++top]=lca;
sta[++top]=u;
}
for(int i=;i<top;i++)add(sta[i],sta[i+]);
sm=; mn=N; len=;
dfs(sta[]); printf("%lld %d %d\n",sm,mn,len);
}
}
int main()
{
bin[]=;for(int i=;i<=;i++)bin[i]=bin[i-]<<;
n=rdn();
for(int i=,u,v;i<n;i++)
u=rdn(),v=rdn(),add(u,v),add(v,u);
dfs(,); int Q=rdn();
while(Q--)Tr::solve();
return ;
}

bzoj 3611(洛谷 4103) [Heoi2014]大工程——虚树的更多相关文章

  1. 洛谷P4103 [HEOI2014]大工程(虚树 树形dp)

    题意 链接 Sol 虚树. 首先建出虚树,然后直接树形dp就行了. 最大最小值直接维护子树内到该节点的最大值,然后合并两棵子树的时候更新一下答案. 任意两点的路径和可以考虑每条边两边的贡献,\(d[x ...

  2. 洛谷4103 HEOI2014大工程(虚树+dp)

    又是一道虚树好题啊 我们建出来虚树,然后考虑dp过程,我们分别令\(sum[x],mndis[x],mxdis[x],size[x]\)为子树内的路径长度和,最短链,最长链,子树内关键点个数. 对于一 ...

  3. bzoj 3611: [Heoi2014]大工程 虚树

    题目: 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 ...

  4. luogu P4103 [HEOI2014]大工程 虚树 + 树形 DP

    Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道.  我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上.  在 2 个国家 a,b 之间建一条新通 ...

  5. bzoj 3611[Heoi2014]大工程 虚树+dp

    题意: 给一棵树 每次选 k 个关键点,然后在它们两两之间 新建 C(k,2)条 新通道. 求: 1.这些新通道的代价和 2.这些新通道中代价最小的是多少 3.这些新通道中代价最大的是多少 分析:较常 ...

  6. BZOJ.3611.[HEOI2014]大工程(虚树 树形DP)

    题目链接 要求的和.最大值.最小值好像都可以通过O(n)的树形DP做,总询问点数<=2n. 于是建虚树就可以了.具体DP见DP()函数,维护三个值sum[],mx[],mn[]. sum[]要开 ...

  7. BZOJ 3611 [Heoi2014]大工程 ——虚树

    虚树第二题.... 同BZOJ2286 #include <map> #include <cmath> #include <queue> #include < ...

  8. Luogu 4103 [HEOI2014]大工程

    BZOJ 3611 明明在BZOJ上是$6s$的时限,怎么到Luogu上就变成$4s$了…… 按照套路建出虚树,点之间的距离可以变成边权表示在虚树上,然后考虑如何树形$dp$. 最大值和最小值应当比较 ...

  9. 【HEOI2014】大工程<虚树>

    虚树 我们每天都用心思索着,这究竟是为了什么呢?我想我也不知道,只是觉得如果人不思考问题就很无聊. 我觉得虚树不是什么数据结构,就是一种技巧或者工具.它能把树中\(k\)个关键点以\(O(klogk) ...

随机推荐

  1. Web Service基本概念

    Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术.是:通过SOAP ...

  2. 折叠菜单slideUp

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. splunk 通过rest http导入数据

    使用 HTTP Event Collector go to Settings > Data inputs > HTTP Event Collector. Then click the Gl ...

  4. hadoop mongodb install(3)

    reference:http://dblab.xmu.edu.cn/blog/868-2/ root@iZuf68496ttdogcxs22w6sZ:~# mv mongodb-linux-x86_6 ...

  5. 51nod算法马拉松28-a

    题解:水体一枚 按照贪心的思想求出是2的k次方,然后高精度计算 代码: #include<bits/stdc++.h> using namespace std; ; int ans,n,a ...

  6. Oracle top 查询TOP SQL

    有时Oracle数据库服务器,系统CPU爆高,通过Top命令可以查看到占用CPU最高的进程 我们需要记住前几个TOP的pid号,带入下面的SQL,到数据库中查询运行的进程.服务器.用户.SQL.等待等 ...

  7. DevExpress v17.2新版亮点——CodeRush篇(二)

    用户界面套包DevExpress v17.2日前终于正式发布,本站将以连载的形式为大家介绍各版本新增内容.本文将介绍了CodeRush v17.2 的新功能,快来下载试用新版本! 支持XAML 标记扩 ...

  8. Python与系统的交互方式

    本节内容 os与commands模块 subprocess模块 subprocess.Popen类 总结 我们几乎可以在任何操作系统上通过命令行指令与操作系统进行交互,比如Linux平台下的shell ...

  9. 使用Git进行本地提交后,未上传提交,却不小心删除了本地提交或提交所在分支,怎么办?????

    使用Git进行本地提交后,未上传提交,却不小心删除了本地提交或提交所在分支,怎么办????? 不要紧!!!! 可以使用git reflog命令来帮助恢复删除的本地提交! 运行以下命令你就知道怎么用了! ...

  10. vue-resource 上传图片

    const formData = new FormData()formData.append('file',img,params.name);formData.append('id',params.i ...