[Bzoj3611][Heoi2014]大工程(虚树)
3611: [Heoi2014]大工程
Time Limit: 60 Sec Memory Limit: 512 MB
Submit: 2000 Solved: 837
[Submit][Status][Discuss]
Description
Input
第一行 n 表示点数。
Output
输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。
Sample Input
Sample Output
HINT
n<=1000000
Source
题解:
其实数据范围第二句话就摆明是虚树了。。
然后看看这道题要我们做啥,求虚树关键点间最长链,最短链,两两距离和。。
关于距离和,我们只用在dfs时考虑一下当前点,和它儿子结点的边会有多少点对经过就行。
设总关键点为k,一个点x子树所包含关键点数量为sz[x]
当然就是(k - sz[son]) * sz[son]次啦。设每个点到它父亲边被经过次数为cnti
距离就是 dep[son] - dep[now]。设为这个距离为wi
答案就是

就这样我们把第一个询问做出来了。
第二第三询问树上最长最短链,noip--难度。但是有树上有关键点之间的lca啊,当它为链的起点或终点时答案会增大。
然后仔细一想我们只有在当前点为关键点时才会计算单条链贡献。
因为虚点都是关键点间lca所以不会出现虚点为叶子结点,这样就保证起点和终点不会是虚点了。
然后就简单虚树上dp了。
AC代码:
# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e6 + ;
const int inf = 0x3f3f3f3f;
int sz[N],hson[N],top[N],dep[N],que[N],k,a[N],g[N];LL f[N];
int head[N],dt,tot,fa[N],id[N],n,m,mx[N],mi[N],ans1,ans2;
struct Edge{
int to,nex;
}edge[N << ];
void AddEdge(int u,int v)
{
if(u == v)return;
edge[++dt] = (Edge){v,head[u]};
head[u] = dt;
}
void dfs(int u)
{
sz[u] = ;
for(int i = head[u];i;i = edge[i].nex)
{
if(sz[edge[i].to])continue;
dep[edge[i].to] = dep[u] + ;
fa[edge[i].to] = u;
dfs(edge[i].to);
sz[u] += sz[edge[i].to];
if(sz[hson[u]] < sz[edge[i].to])hson[u] = edge[i].to;
}
}
void dfs(int u,int tp)
{
top[u] = tp;id[u] = ++tot;
if(hson[u])dfs(hson[u],tp);
for(int i = head[u];i;i = edge[i].nex)
if(!id[edge[i].to])dfs(edge[i].to,edge[i].to);
head[u] = ;
}
int lca(int u,int v)
{
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]])swap(u,v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
bool cmp(int x,int y){return id[x] < id[y];}
void dp(int u)
{
sz[u] = g[u];mx[u] = ;mi[u] = inf;f[u] = ;
for(int i = head[u];i;i = edge[i].nex)
{
int w = dep[edge[i].to] - dep[u];
dp(edge[i].to);sz[u] += sz[edge[i].to];
ans1 = min(ans1,mi[u] + mi[edge[i].to] + w);mi[u] = min(mi[u],mi[edge[i].to] + w);
ans2 = max(ans2,mx[u] + mx[edge[i].to] + w);mx[u] = max(mx[u],mx[edge[i].to] + w);
f[u] += f[edge[i].to] + 1LL * sz[edge[i].to] * (k - sz[edge[i].to]) * w;
}
if(g[u])ans1 = min(ans1,mi[u]),ans2 = max(ans2,mx[u]),mi[u] = ;
head[u] = g[u] = ;
}
void solve()
{
scanf("%d",&k);int top,gr;ans1 = inf;top = dt = ans2 = ;ans1 = inf;
for(int i = ;i <= k;i++)scanf("%d",&a[i]),g[a[i]] = ;
sort(a + ,a + k + ,cmp);
for(int i = ;i <= k;i++)
{
if(!top){que[++top] = a[i];continue;}
gr = lca(que[top],a[i]);
while(id[gr] < id[que[top]])
{
if(id[gr] >= id[que[top - ]])
{
AddEdge(gr,que[top]);
if(que[--top] != gr)que[++top] = gr;
break;
}
AddEdge(que[top - ],que[top]);top--;
}
if(que[top] != a[i])que[++top] = a[i];
}
top--;
while(top)AddEdge(que[top],que[top + ]),top--;
dp(que[]);
printf("%lld %d %d\n",f[que[]],ans1,ans2);
}
int main()
{
scanf("%d",&n);int x,y;
for(int i = ;i < n;i++)
{
scanf("%d %d",&x,&y);
AddEdge(x,y);AddEdge(y,x);
}
dfs();dfs(,);
scanf("%d",&m);
while(m--)solve();
}
[Bzoj3611][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.这些新通道中代价最大的是多少 分析:较常 ...
- [BZOJ3611][Heoi2014]大工程
[BZOJ3611][Heoi2014]大工程 试题描述 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 ...
- [BZOJ3611][Heoi2014]大工程(虚树上DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 2464 Solved: 1104[Submit][Statu ...
随机推荐
- Javaweb学习笔记7—JDBC技术
今天来讲javaweb的第7阶段学习. JDBC技术,关于JDBC本篇博客只介绍了它的一部分,后面博客会更加深入探讨. 老规矩,首先先用一张思维导图来展现今天的博客内容. ps:我的思维是用的 ...
- ubuntu4.04服务器添加虚拟主机
buntu 14.04配置虚拟主机 虚拟主机常用于在一个单独的IP地址上提供多个域名的网站服务.如果有人想在单个VPS的单个IP地址运行多个网站,这是非常有用的.在这个教程中,让我告诉你如何设置在 ...
- SEO 第八章
SEO第八章 本次课目标: 1. 网站外部优化的外链优化 2. 网站流量分析 1. 什么叫做外链? 外链也叫反向链接,指的是从别的网站指向我自己的网站的链接. 2. 外链的作用? l 外链可 ...
- 在Eclipse中通过JDBC连接MySQL步骤,非常详细!
通过JDBC连接MySQL基本步骤代码讲解步骤可能遇到的Bug基本步骤JDBC访问MySQL 1.加载JDBC驱动器—>哪个project需要,就添加到该project的jdbc文件夹下,我的j ...
- 前端什么是BFC
什么是BFC? 全称块级格式化上下文?什么意思不懂.看了好多博客,基本都是抄的,真心都不是大白话.我今天来总结一下,用菜鸟级别的语言来描述. BFC 应该可以抽象成一个 独立的个体,出淤泥而不染的白莲 ...
- hql语法002
1. package cn.jbit.hibernatedemo.test; import java.util.Iterator; import java.util.List; import org. ...
- 全局/局部变量、宏、const、static、extern
#pragma mark--全局变量和局部变量 根据变量的作用域,变量可以分为: 一.全局变量 1> 定义:在函数外面定义的变量2> 作用域:从定义变量的那一行开始,一直到文件结尾(能被后 ...
- CodeForces - 930A Peculiar apple-tree(dfs搜索)
题目: 给出一个树,这棵树上每个结点每一秒都会结出一颗果实,果实每经过一秒就会落向下一个结点,如果一个结点在同一时刻上的果实两两抵消,问最后在根节点处一共有多少个果实. 思路: dfs直接搜索统计这棵 ...
- [kuangbin带你飞]专题五 并查集
并查集的介绍可以看下https://www.cnblogs.com/jkzr/p/10290488.html A - Wireless Network POJ - 2236 An earthquake ...
- JavaScript中的内置函数
JavaScript中的内置函数 制作人:全心全意 在使用JavaScript语言时,除了可以自定义函数之外,还可以使用JavaScript的内置函数,这些内置函数是由JavaScript语言自身提供 ...