[BZOJ3611] [Heoi2014]大工程(DP + 虚树)
$dp[i][0]$表示节点i到子树中的所有点的距离之和
$dp[i][1]$表示节点i到子树中最近距离的点的距离
$dp[i][2]$表示节点i到子树中最远距离的点的距离
建好虚树后dp即可。
因为对于虚树掌握的还不是很熟,有些细节还是要注意。
虚树中可能会加入一些lca节点,这些节点在dp的时候是不应该统计的。
对于本题来说,别忘记考虑某一节点不同子树中点对的组合。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 2000010
#define LL long long using namespace std; LL ans1, ans2, dp[N][3];
int n, cnt, rp, m, top, T;
int head[N], to[N], nex[N], val[N], dis[N], size[N], dfn[N], deep[N], f[N][21], q[N], s[N], flag[N]; inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
return x * f;
} inline void add(int x, int y)
{
to[cnt] = y;
nex[cnt] = head[x];
head[x] = cnt++;
} inline void dfs1(int u)
{
int i, v;
dfn[u] = ++rp;
deep[u] = deep[f[u][0]] + 1;
for(i = 0; f[u][i]; i++) f[u][i + 1] = f[f[u][i]][i];
for(i = head[u]; ~i; i = nex[i])
{
v = to[i];
if(!dfn[v])
{
f[v][0] = u;
dis[v] = dis[u] + 1;
dfs1(v);
}
}
head[u] = -1;
} inline int calc_lca(int x, int y)
{
int i;
if(deep[x] < deep[y]) swap(x, y);
for(i = 20; i >= 0; i--)
if(deep[f[x][i]] >= deep[y]) x = f[x][i];
if(x == y) return x;
for(i = 20; i >= 0; i--)
if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return f[x][0];
} inline bool cmp(int x, int y)
{
return dfn[x] < dfn[y];
} inline void dfs2(int u)
{
int i, v;
size[u] = flag[u];
dp[u][1] = 1e9, dp[u][0] = dp[u][2] = 0;
for(i = head[u]; ~i; i = nex[i])
{
v = to[i];
dfs2(v);
size[u] += size[v];
ans1 = min(ans1, dp[u][1] + dp[v][1] + dis[v] - dis[u]);
ans2 = max(ans2, dp[u][2] + dp[v][2] + dis[v] - dis[u]);
dp[u][0] += dp[v][0] + 1ll * size[v] * (m - size[v]) * (dis[v] - dis[u]);
dp[u][1] = min(dp[u][1], dis[v] - dis[u] + dp[v][1]);
dp[u][2] = max(dp[u][2], dis[v] - dis[u] + dp[v][2]);
}
if(flag[u])
{
ans1 = min(ans1, dp[u][1]);
ans2 = max(ans2, dp[u][2]);
dp[u][1] = 0;
}
head[u] = -1;
} inline void solve()
{
int i, lca;
m = read();
top = cnt = 0;
for(i = 1; i <= m; i++) q[i] = read(), flag[q[i]] = 1;
sort(q + 1, q + m + 1, cmp);
for(i = 1; i <= m; i++)
{
if(!top)
{
s[++top] = q[i];
continue;
}
lca = calc_lca(s[top], q[i]);
while(dfn[lca] < dfn[s[top]])
{
if(dfn[lca] >= dfn[s[top - 1]])
{
add(lca, s[top]);
if(s[--top] != lca) s[++top] = lca;
break;
}
add(s[top - 1], s[top]), top--;
}
s[++top] = q[i];
}
while(top > 1) add(s[top - 1], s[top]), top--;
ans2 = 0;
ans1 = 1ll * 1e9 * 1e9;
dfs2(s[1]);
printf("%lld %lld %lld\n", dp[s[1]][0], ans1, ans2);
for(i = 1; i <= m; i++) flag[q[i]] = 0;
} int main()
{
int i, x, y;
n = read();
memset(head, -1, sizeof(head));
for(i = 1; i < n; i++)
{
x = read();
y = read();
add(x, y);
add(y, x);
}
dfs1(1);
T = read();
while(T--) solve();
return 0;
}
[BZOJ3611] [Heoi2014]大工程(DP + 虚树)的更多相关文章
- [Bzoj3611][Heoi2014]大工程(虚树)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 2000 Solved: 837[Submit][Status ...
- BZOJ3611 [Heoi2014]大工程 【虚树】
题目 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a ...
- 【BZOJ3611】大工程(虚树,动态规划)
[BZOJ3611]大工程(虚树,动态规划) 题面 BZOJ Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树 ...
- [BZOJ3611][Heoi2014]大工程(虚树上DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 2464 Solved: 1104[Submit][Statu ...
- bzoj 3611 [Heoi2014]大工程(虚树+DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 408 Solved: 190[Submit][Status] ...
- 【BZOJ3611】大工程(虚树,DFS序,树形DP)
题意:有一棵树,树有边权,有若干次询问,给出一些点,求: 1.这些点互相之间的距离之和 2.点对距离中的最大和最小值 n<=1000000 q<=50000并且保证所有k之和<=2* ...
- 洛谷4103 HEOI2014大工程(虚树+dp)
又是一道虚树好题啊 我们建出来虚树,然后考虑dp过程,我们分别令\(sum[x],mndis[x],mxdis[x],size[x]\)为子树内的路径长度和,最短链,最长链,子树内关键点个数. 对于一 ...
- [BZOJ3611][Heoi2014]大工程
[BZOJ3611][Heoi2014]大工程 试题描述 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 ...
- BZOJ2286 [Sdoi2011]消耗战 和 BZOJ3611 [Heoi2014]大工程
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6371 Solved: 2496[Submit][Statu ...
- BZOJ3611:[HEOI2014]大工程(树形DP,虚树)
Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通 ...
随机推荐
- C/C++ 内存分配方式,堆区,栈区,new/delete/malloc/free
内存分配方式 内存分配方式有三种: [1] 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量, static 变量. [2] 在栈上创建.在执行函 ...
- SQL 视图、事务
假设看多个不同的表 select *from student ,score,course,teacher 有重复的 改为select student.Sno,sname,ssex,sbirthd ...
- 洛谷 P1732 活蹦乱跳的香穗子
题目描述 香穗子在田野上调蘑菇!她跳啊跳,发现自己很无聊,于是她想了一个有趣的事情,每个格子最多只能经过1次,且每个格子都有其价值 跳的规则是这样的,香穗子可以向上下左右四个方向跳到相邻的格子,并且她 ...
- osx launchpad图标的删除
安装了个parallels desktop之后,OSX中的launchpad中的图标多了不少,可是好多都不是我自己想要的,我们该怎么删除或者修改呢,下面介绍一些方法: ①直接操作Appications ...
- CentOS7——防火墙设置
1.查看firewall服务状态 systemctl status firewalld 2.查看firewall的状态firewall-cmd --state 3.开启.重启.关闭.firewalld ...
- 【转】Spring, MyBatis 多数据源的配置和管理
同一个项目有时会涉及到多个数据库,也就是多数据源.多数据源又可以分为两种情况: 1)两个或多个数据库没有相关性,各自独立,其实这种可以作为两个项目来开发.比如在游戏开发中一个数据库是平台数据库,其它还 ...
- CPP-基础:cout
C++编程语言互换流中的标准输出流,需要iostream.h支持.读为 "c out". 使用范例 //用户输入的数字由cin保存于变量a中,并通过cout输出. #include ...
- Codeforces Round #275 (Div. 2)-A. Counterexample
http://codeforces.com/contest/483/problem/A A. Counterexample time limit per test 1 second memory li ...
- 在tomcat中配置连接池
在tomcat的conf/Catalina/localhost目录下配置项目路径,tomcat启动是会直接根据配置去加载项目. 虽然配置就一句话,但经常忘,今天记下来. 如果你的项目成名是:mypro ...
- jExcelAPI导入导出excel
MS的电子表格(Excel)是Office的重要成员,是保存统计数据的一种常用格式.作为办公文档,势必要涉及到的电子文档的交换,Excel是一种在企业中非常通用的文件格式,打印和管理也比较方便.在 ...