Description

国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。 
我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。 
在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
 现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间 新建 C(k,2)条 新通道。
现在对于每个计划,我们想知道:
 1.这些新通道的代价和
 2.这些新通道中代价最小的是多少 
3.这些新通道中代价最大的是多少
 

Input

第一行 n 表示点数。

 接下来 n-1 行,每行两个数 a,b 表示 a 和 b 之间有一条边。
点从 1 开始标号。 接下来一行 q 表示计划数。
对每个计划有 2 行,第一行 k 表示这个计划选中了几个点。
 第二行用空格隔开的 k 个互不相同的数表示选了哪 k 个点。
 

Output

输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。

 

Sample Input

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

Sample Output

3 3 3
6 6 6
1 1 1
2 2 2
2 2 2
/*
f[i]表示以i为根的子树的路径和
f[i]=f[son[i]]+siz[son[y]]*(cnt-siz[son[y]])*dis(i,son[i])
maxs[i]表示以i为根的子树的节点到i的最大长度
用maxs[i]+maxs[son[i]]+dis(i,son[i])来更新答案。
然后在虚树上做DP
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 1000010
#define lon long long
#define inf 1000000000
using namespace std;
int n,m,dfn[N],dep[N],tim,fa[N][],a[N],num;
int g[N],sta[N],top,siz[N],mins[N],maxs[N],ans1,ans2;
lon f[N];
bool cmp(int x,int y){return dfn[x]<dfn[y];}
struct Node{
int head[N],son[N*],pre[N*],cnt;
void add(int u,int v){
son[++cnt]=v;pre[cnt]=head[u];head[u]=cnt;
}
void dfs1(int u){
dfn[u]=++tim;
for(int i=;i<=;i++) fa[u][i]=fa[fa[u][i-]][i-];
for(int i=head[u];i;i=pre[i])
if(son[i]!=fa[u][]){
fa[son[i]][]=u;
dep[son[i]]=dep[u]+;
dfs1(son[i]);
}
}
void dfs2(int x){
siz[x]=g[x];maxs[x]=;mins[x]=inf;f[x]=;
for(int i=head[x];i;i=pre[i]){
int d=dep[son[i]]-dep[x];
dfs2(son[i]);siz[x]+=siz[son[i]];
ans1=min(ans1,mins[x]+mins[son[i]]+d);
mins[x]=min(mins[x],mins[son[i]]+d);
ans2=max(ans2,maxs[x]+maxs[son[i]]+d);
maxs[x]=max(maxs[x],maxs[son[i]]+d);
f[x]+=f[son[i]]+1LL*siz[son[i]]*(num-siz[son[i]])*d;
}
if(g[x]) ans1=min(ans1,mins[x]),ans2=max(ans2,maxs[x]),mins[x]=;
head[x]=;
}
}g1,g2;
int lca(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
int t=dep[a]-dep[b];
for(int i=;~i;i--) if(t&(<<i)) a=fa[a][i];
if(a==b) return a;
for(int i=;~i;i--)
if(fa[a][i]!=fa[b][i])
a=fa[a][i],b=fa[b][i];
return fa[a][];
}
void work(){
top=;
for(int i=;i<=num;i++){
if(!top){sta[++top]=a[i];continue;}
int anc=lca(a[i],sta[top]);
while(dep[anc]<dep[sta[top]]){
if(dep[anc]>=dep[sta[top-]]){
g2.add(anc,sta[top]);
top--;
if(sta[top]!=anc) sta[++top]=anc;
break;
}
else g2.add(sta[top-],sta[top]),top--;
}
if(sta[top]!=a[i]) sta[++top]=a[i];
}
while(top>) g2.add(sta[top-],sta[top]),top--;
ans1=inf;ans2=;g2.dfs2(sta[]);
printf("%lld %d %d\n",f[sta[]],ans1,ans2);
for(int i=;i<=num;i++) g[a[i]]=;g2.cnt=;
}
int main(){
scanf("%d",&n);
for(int i=;i<n;i++){
int u,v;scanf("%d%d",&u,&v);
g1.add(u,v);g1.add(v,u);
}
g1.dfs1();scanf("%d",&m);
for(int i=;i<=m;i++){
scanf("%d",&num);
for(int j=;j<=num;j++) scanf("%d",&a[j]),g[a[j]]=;
sort(a+,a+num+,cmp);
work();
}
return ;
}

大工程(bzoj 3611)的更多相关文章

  1. bzoj 3611: [Heoi2014]大工程 && bzoj 2286: [Sdoi2011消耗战

    放波建虚树的模板. 大概是用一个栈维护根节点到当前关键点的一条链,把其他深度大于lca的都弹出去. 每次做完记得复原. 还有sort的时候一定要加cmp!!! bzoj 3611 #include&l ...

  2. 【BZOJ】【3611】【HEOI2014】大工程

    虚树+树形DP 本题100W的点数……不用虚树真的好吗…… Orz ZYF 我的感悟: dp的过程跟SPOJ 1825 FTOUR2 的做法类似,依次枚举每个子树,从当前子树和之前的部分中各找一条最长 ...

  3. bzoj 3611 [Heoi2014]大工程(虚树+DP)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 408  Solved: 190[Submit][Status] ...

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

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

  5. BZOJ 3611 大工程 (虚树)

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

  6. 3611: [Heoi2014]大工程

    3611: [Heoi2014]大工程 链接 分析: 树形dp+虚树. 首先建立虚树,在虚树上dp. dp:sum[i]为i的子树中所有询问点之间的和.siz[i]为i的子树中有多少询问点,mn[i] ...

  7. 【BZOJ3611】大工程(虚树,动态规划)

    [BZOJ3611]大工程(虚树,动态规划) 题面 BZOJ Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树 ...

  8. BZOJ2286 [Sdoi2011]消耗战 和 BZOJ3611 [Heoi2014]大工程

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6371  Solved: 2496[Submit][Statu ...

  9. [Bzoj3611][Heoi2014]大工程(虚树)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 2000  Solved: 837[Submit][Status ...

随机推荐

  1. python获取Excel数据

    Python中一般使用xlrd(excel read)来读取Excel文件,使用xlwt(excel write)来生成Excel文件(可以控制Excel中单元格的格式),需要注意的是,用xlrd读取 ...

  2. C5509A启动使用定时器

    #include <stdio.h> #include <csl.h> #include <csl_pll.h> #include <csl_chip.h&g ...

  3. python面向对象的约束和自定义异常

    基于人为来约束: 即人为主动抛出异常 class BaseMessage(object): def send(self,x1): """ 必须继承BaseMessage, ...

  4. 001.我的第一个Java程序

    第一步安装JDK 第二步设置PATH路径 设置Windows的PATH 路径 方法一:直接设置添加PATH C:\Program Files\Java\jdk1.8.0_92\bin 方法二: 先增加 ...

  5. 编译IOS下 libpcap1.7.2

    1.修改build-libpcap.sh libpcap版本号 2.执行脚本编译 出现问题: 2.发现configure过后,Makefile存在问题 实际configure的-arch armv7s ...

  6. 玩转Node.js(三)

    玩转Node.js(三) 上一节对于Nodejs的HTTP服务进行了较为详细的解析,而且也学会了将代码进行模块化,模块化以后每个功能都在单独的文件中,有利于代码的维护.接下来,我们要想想如何处理不同的 ...

  7. Cookies 、 Session 和 token 的区别

    这篇文章写的 Cookies 和 Session的区别 比较详细,也很好理解,可以学习下:https://blog.csdn.net/axin66ok/article/details/6175522 ...

  8. Windows下python 3 pip程序升级异常问题及pip常用命令

    最近在学习,Selenium+Python自动化,在安装selenium包的时候,出现无法安装的情况,并提示Pip有新的版本,我的版本太低了.然后安装系统提示操作,pip升级也出现异常,报错timeo ...

  9. jenkins构建定时任务

    jenkins构建定时任务的主要两种形式 1.Build periodically:周期性构建项目,无论有没有代码更新到时间都会构建项目 2.Poll SCM:定时检查源码变更(根据SCM软件的版本号 ...

  10. RAID介绍和实现

    RAID的全称是廉价磁盘冗余阵列(Redundant Array of Inexpensive Disks),于1987年由美国Berkeley 大学的两名工程师提出的. RAID出现的,最初目的是将 ...