BZOJ3611 [Heoi2014]大工程 【虚树】
题目
国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。
我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。
在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间 新建 C(k,2)条 新通道。
现在对于每个计划,我们想知道:
1.这些新通道的代价和
2.这些新通道中代价最小的是多少
3.这些新通道中代价最大的是多少
输入格式
第一行 n 表示点数。
接下来 n-1 行,每行两个数 a,b 表示 a 和 b 之间有一条边。
点从 1 开始标号。 接下来一行 q 表示计划数。
对每个计划有 2 行,第一行 k 表示这个计划选中了几个点。
第二行用空格隔开的 k 个互不相同的数表示选了哪 k 个点
输出格式
输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。
输入样例
10
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
输出样例
3 3 3
6 6 6
1 1 1
2 2 2
2 2 2
提示
n<=1000000
q<=50000并且保证所有k之和<=2*n
题解
好久没写虚树了,一写整个人就虚完了,
这题没什么难点,建完虚树后比较基础的树形dp就完了
最大值就维护当前子树最大值,然后尝试将一个子树最大值与当前子树中最大值相加更新答案
最小值类似
总和呢,考虑一个子树内的所有点要往上走,都要经过这条边,那么有\(siz[son] * (k - siz[son])\)种组合,乘以边长作为贡献
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 1000005,maxm = 2000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int hh[maxn],nn = 2;
int h[maxn],ne = 2,de[maxn];
struct EDGE{int to,nxt,w;}e[maxm],ed[maxm];
inline void add(int u,int v){
e[nn] = (EDGE){v,hh[u],0}; hh[u] = nn++;
e[nn] = (EDGE){u,hh[v],0}; hh[v] = nn++;
}
inline void build(int u,int v,int w){
ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v],w}; h[v] = ne++;
de[u]++; de[v]++;
}
int n,K,a[maxn],fa[maxn][21],dep[maxn],dfn[maxn],cnt;
void dfs(int u){
dfn[u] = ++cnt;
for (int i = 1; i <= 20; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
for (int k = hh[u],to; k; k = e[k].nxt)
if ((to = e[k].to) != fa[u][0]){
fa[to][0] = u;
dep[to] = dep[u] + 1;
dfs(to);
}
}
int lca(int u,int v){
if (dep[u] < dep[v]) swap(u,v);
for (int i = 0,d = dep[u] - dep[v]; (1 << i) <= d; i++)
if ((1 << i) & d) u = fa[u][i];
if (u == v) return u;
for (int i = 20; i >= 0; i--)
if (fa[u][i] != fa[v][i]){
u = fa[u][i];
v = fa[v][i];
}
return fa[u][0];
}
int st[maxn],top;
inline bool cmp(const int& a,const int& b){
return dfn[a] < dfn[b];
}
void rebuild(){
top = 0; ne = 2;
sort(a + 1,a + 1 + K,cmp);
st[++top] = 1;
for (int i = 1; i <= K; i++){
int u = a[i],v = lca(u,st[top]);
if (v == st[top]) st[++top] = u;
else {
while (true){
if (dep[v] >= dep[st[top - 1]]){
build(v,st[top],dep[st[top]] - dep[v]);
top--;
st[++top] = v;
break;
}
build(st[top],st[top - 1],dep[st[top]] - dep[st[top - 1]]);
top--;
}
st[++top] = u;
}
}
while (top > 1) build(st[top],st[top - 1],dep[st[top]] - dep[st[top - 1]]),top--;
}
int tag[maxn];
LL sum,gmax,gmin,mn[maxn],mx[maxn],siz[maxn];
void DFS(int u){
mx[u] = tag[u] ? 0 : -INF;
mn[u] = tag[u] ? 0 : INF;
siz[u] = tag[u];
Redge(u) if (dep[to = ed[k].to] > dep[u]){
DFS(to);
sum += siz[to] * (K - siz[to]) * ed[k].w;
siz[u] += siz[to];
gmin = min(gmin,mn[u] + mn[to] + ed[k].w);
gmax = max(gmax,mx[u] + mx[to] + ed[k].w);
mn[u] = min(mn[u],mn[to] + ed[k].w);
mx[u] = max(mx[u],mx[to] + ed[k].w);
}
h[u] = de[u] = 0;
}
void solve(){
rebuild();
for (int i = 1; i <= K; i++) tag[a[i]] = 1;
sum = gmax = 0;
gmin = INF;
if (de[1] == 1 && !tag[1]){
DFS(ed[h[1]].to);
h[1] = de[1] = 0;
}
else DFS(1);
printf("%lld %lld %lld\n",sum,gmin,gmax);
for (int i = 1; i <= K; i++) tag[a[i]] = 0;
}
int main(){
n = read();
for (int i = 1; i < n; i++) add(read(),read());
dfs(1);
int q = read();
while (q--){
K = read();
for (int i = 1; i <= K; i++) a[i] = read();
solve();
}
return 0;
}
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]大工程(虚树)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 2000 Solved: 837[Submit][Status ...
- [BZOJ3611][Heoi2014]大工程(虚树上DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 2464 Solved: 1104[Submit][Statu ...
随机推荐
- freebsd安装ports
/etc/portsnap.conf 里面更改 SERVERNAME=portsnap.hshh.org portsnap的命令比较少 fetch 获取数据 extract 释放全部ports upd ...
- powershell 版本问题
Login-AzureRmAccount : 无法将“Login-AzureRmAccount”项识别为 cmdlet.函数.脚本文件或可运行程序的名称.请检查名称的拼写,如果包括路径,请确保路径正确 ...
- C++实现动态数组
实现一个动态数组,要求对于随机访问可以在常数时间完成,可以通过push_back向数据的尾部追加元素,可以通过pop_back删除尾部元素,能够满足常见的数组操作. LINE 2016年春招笔试 ...
- htmlunit爬取js异步加载后的页面
直接上代码: 一. index.html 调用后台请求获取content中的内容. <html> <head> <script type="text/javas ...
- UVA 1412 Fund Management (预处理+状压dp)
状压dp,每个状态可以表示为一个n元组,且上限为8,可以用一个九进制来表示状态.但是这样做用数组开不下,用map离散会T. 而实际上很多九进制数很多都是用不上的.因此类似uva 1601 Mornin ...
- 1991: C语言实验——大小写转换
1991: C语言实验——大小写转换 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 183 Solved: 109[Submit][Status][We ...
- Asp.Net Core 进阶(三)—— IServiceCollection依赖注入容器和使用Autofac替换它
Asp.Net Core 提供了默认的依赖注入容器 IServiceCollection,它是一个轻量级的依赖注入容器,所以功能不多,只是提供了基础的一些功能,要实现AOP就有点麻烦,因此在实际工作当 ...
- pandas小结
pandas part I: # 总结: DataFrame.loc[0:5] 一共6行数据,而切片[0:5]只有5个数据 在对df的行数据删除后,有些index已缺失,此时用 iloc[]来按照位置 ...
- Open Scene Graph:让VS支持不含后缀的头文件
让VS支持不含后缀的头文件 看OSG源码时,会遇到不含后缀的头文件无定位信息的尴尬,很让人苦恼. 就是单击VS中“工具菜单栏”——>”选项(O)….”如下图所示: 菜单项,弹出选项对话框,单击“ ...
- JAVA web项目转客户端(nativefier)
1.环境:windows 2.下载node.js 3.安装mode.js;记住安装目录 4.命令行进入安装目录 5.执行语句: npm install nativefier –g 进行安装 6.新建空 ...