3611: [Heoi2014]大工程

Time Limit: 60 Sec  Memory Limit: 512 MB
Submit: 408  Solved: 190
[Submit][Status][Discuss]

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

HINT

n<=1000000

q<=50000并且保证所有k之和<=2*n 

Source

【思路】

虚树+树上DP

对每次询问构造虚树,在虚树上进行DP。

ans1和ans2即树上的最长/短链问题,利用前缀和思想可以求解。

   设sum[x] = ∑(sum[y] + w * size[y]); 则有

    ans += ∑((sum[y] + w * size[y]) * (size[x] - size[y]));

  其中size[x]表示以x为根的子树包含的询问点数目,w为x->y的边长。

   好大的工程=-=

【代码】

  1. #include<cstdio>
  2. #include<vector>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7.  
  8. const int N = +;
  9. const int INF = 1e9+1e9;
  10. const int D = ;
  11.  
  12. typedef long long LL;
  13. vector<int> G[N],g[N];
  14. int d[N],dfn[N];
  15. int n,q,dfsc;
  16.  
  17. void adde(int u,int v) {
  18. if(u!=v) G[u].push_back(v); else return;
  19. }
  20. bool cmp(const int& lhs,const int& rhs) {
  21. return dfn[lhs]<dfn[rhs];
  22. }
  23. ////////////////////////////////////////////////////lca which cuts down about 5000ms
  24. int siz[N],top[N],son[N],fa[N];
  25. void dfs1(int u) {
  26. siz[u]=,son[]=; dfn[u]=++dfsc;
  27. for(int i=;i<g[u].size();i++) {
  28. int v=g[u][i];
  29. if(v!=fa[u]) {
  30. fa[v]=u; d[v]=d[u]+;
  31. dfs1(v);
  32. siz[u]+=siz[v];
  33. if(siz[v]>siz[son[u]]) son[u]=v;
  34. }
  35. }
  36. }
  37. void dfs2(int u,int tp) {
  38. top[u]=tp;
  39. if(son[u]) dfs2(son[u],tp);
  40. for(int i=;i<g[u].size();i++) {
  41. int v=g[u][i];
  42. if(v!=son[u] && v!=fa[u]) dfs2(v,v);
  43. }
  44. }
  45. int LCA(int u,int v) {
  46. while(top[u]!=top[v])
  47. if(d[top[u]]>=d[top[v]]) u=fa[top[u]];
  48. else v=fa[top[v]];
  49. return d[u]<d[v]? u:v;
  50. }
  51. ////////////////////////////////////////////////
  52. LL sum[N],ans;
  53. int ans1,ans2,mi[N],mx[N],sz[N]; bool ifq[N];
  54. int dp(int u) {
  55. sum[u]=; sz[u]=ifq[u];
  56. mi[u]=ifq[u]? :INF;
  57. mx[u]=ifq[u]? :-INF;
  58. for(int i=;i<G[u].size();i++) {
  59. int v=G[u][i],w=d[v]-d[u];
  60. dp(v);
  61. sz[u]+=sz[v];
  62. sum[u]+=sum[v]+sz[v]*w;
  63. ans1=min(ans1,mi[u]+mi[v]+w);
  64. ans2=max(ans2,mx[u]+mx[v]+w);
  65. mi[u]=min(mi[u],mi[v]+w);
  66. mx[u]=max(mx[u],mx[v]+w);
  67. }
  68. for(int i=;i<G[u].size();i++) {
  69. int v=G[u][i],w=d[v]-d[u];
  70. ans+=(sum[v]+sz[v]*w)*(sz[u]-sz[v]);
  71. }
  72. ifq[u]=; G[u].clear(); //clear
  73. }
  74. void read(int& x) {
  75. char c=getchar();while(!isdigit(c))c=getchar();
  76. x=;while(isdigit(c))x=x*+c-'' , c=getchar();
  77. }
  78. void solve() {
  79. int tot=,top=,k;
  80. static int st[N],h[N];
  81. read(k);
  82. for(int i=;i<=k;i++) read(h[i]),ifq[h[i]]=;
  83. sort(h+,h+k+,cmp);
  84. st[++top]=;
  85. for(int i=;i<=k;i++) {
  86. int p=h[i],lca=LCA(p,st[top]);
  87. for(;;) {
  88. if(d[lca]>=d[st[top-]]) {
  89. adde(lca,st[top]);
  90. top--;
  91. if(st[top]!=lca) st[++top]=lca;
  92. break;
  93. }
  94. adde(st[top-],st[top]); top--;
  95. }
  96. if(st[top]!=p) st[++top]=p;
  97. }
  98. while(--top) adde(st[top],st[top+]);
  99. ans=ans2= , ans1=INF;
  100. dp();
  101. printf("%lld %d %d\n",ans,ans1,ans2);
  102. }
  103. int main() {
  104. read(n);
  105. int u,v;
  106. for(int i=;i<n;i++) {
  107. read(u),read(v);
  108. g[u].push_back(v) , g[v].push_back(u);
  109. }
  110. d[]=; dfs1(); dfs2(,);
  111. read(q);
  112. while(q--) solve();
  113. return ;
  114. }

bzoj 3611 [Heoi2014]大工程(虚树+DP)的更多相关文章

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

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

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

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

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

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

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

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

  5. bzoj 3611(洛谷 4103) [Heoi2014]大工程——虚树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3611 https://www.luogu.org/problemnew/show/P4103 ...

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

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

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

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

  8. [HEOI2014][bzoj3611] 大工程 [虚树+dp]

    题面: 传送门 思路: 又是一道虚树入门级的题目,但是这道题的实际难点在于dp 首先,这道题是可以点分治做的,而且因为6s时限随便浪,所以写点分治也不是不可以 但是,dp因为$O\left(n\rig ...

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

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

随机推荐

  1. [上传下载] C#FileDown文件下载类 (转载)

    点击下载 FileDown.zip 主要功能如下 .参数为虚拟路径 .获取物理地址 .普通下载 .分块下载 .输出硬盘文件,提供下载 支持大文件.续传.速度限制.资源占用小 看下面代码吧 /// &l ...

  2. IOS-objectForKey与valueForKey在NSDictionary中的差异

    从 NSDictionary 取值的时候有两个方法,objectForKey: 和 valueForKey:,这两个方法具体有什么不同呢? 先从 NSDictionary 文档中来看这两个方法的定义: ...

  3. Qt中,当QDockWidget的父窗口是一个不可以拖动的QTabWidget的时候实现拖动的方法

    之前在做有关QDockWidget的内容时候遇到了瓶颈,那就是窗口弹出来之后拖动不了,也不可以放大和缩小,若是弹出来之后设置成了window的flags,也不可以拖动,而且也不是需要的效果. 1.弹出 ...

  4. Java之加密(信息摘要)工具类(依赖:java.security.MessageDigest或org.apache.commons.codec.digest.DigestUtils)

    依赖于java.security.MessageDigest,支持MD5,SHA-1,SHA-256 import java.security.MessageDigest; import java.s ...

  5. 《Velocity java开发指南》中文版(上)转载

    文章引自:http://sakyone.iteye.com/blog/524289 1.开始入门 Velocity是一基于java语言的模板引擎,使用这个简单.功能强大的开发工具,可以很容易的将数据对 ...

  6. 【JQuery学习历程】1.初识JQuery

    1.JQuery简介: JQuery是用js写的JavaScript库,是为了简化js对HTML元素的操作.实现动画效果并方便为网站提供ajax交互: 2.ready()方法: ready()方法和j ...

  7. Jquery Mobile下设置radio控件选中

    问题: .html文件头部引入了: <script src="js/jquery.js"></script> <script src="js ...

  8. shell 1变量注意点

    定义变量时,变量名不加美元符号($),如: variableName="value" 注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样. 删除变量 使用 un ...

  9. 帝国cms 灵动标签调用顶级栏目导航

    [e:loop={"select classname,classpath from [!db.pre!]enewsclass where bclassid=0 order by classi ...

  10. Centos6.4配置Fedora EPEL源附配置hop5.in源

    查看系统版本 cat /etc/redhat-release 下载CentOS 版本所对应的EPEL 的版本 wget http://download.fedoraproject.org/pub/ep ...