3611: [Heoi2014]大工程


Time Limit: 60 Sec  Memory Limit: 512 MB
Submit: 2000  Solved: 837
[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


  1.  

Sample Output


  1.  

HINT


n<=1000000

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

Source


题解:


其实数据范围第二句话就摆明是虚树了。。

然后看看这道题要我们做啥,求虚树关键点间最长链,最短链,两两距离和。。

关于距离和,我们只用在dfs时考虑一下当前点,和它儿子结点的边会有多少点对经过就行。

设总关键点为k,一个点x子树所包含关键点数量为sz[x]

当然就是(k - sz[son]) * sz[son]次啦。设每个点到它父亲边被经过次数为cnti

距离就是 dep[son] - dep[now]。设为这个距离为wi

答案就是

就这样我们把第一个询问做出来了。

第二第三询问树上最长最短链,noip--难度。但是有树上有关键点之间的lca啊,当它为链的起点或终点时答案会增大。

然后仔细一想我们只有在当前点为关键点时才会计算单条链贡献。

因为虚点都是关键点间lca所以不会出现虚点为叶子结点,这样就保证起点和终点不会是虚点了。

然后就简单虚树上dp了。

AC代码:


  1. # include <iostream>
  2. # include <cstdio>
  3. # include <cstring>
  4. # include <algorithm>
  5. using namespace std;
  6. typedef long long LL;
  7. const int N = 1e6 + ;
  8. const int inf = 0x3f3f3f3f;
  9. int sz[N],hson[N],top[N],dep[N],que[N],k,a[N],g[N];LL f[N];
  10. int head[N],dt,tot,fa[N],id[N],n,m,mx[N],mi[N],ans1,ans2;
  11. struct Edge{
  12. int to,nex;
  13. }edge[N << ];
  14. void AddEdge(int u,int v)
  15. {
  16. if(u == v)return;
  17. edge[++dt] = (Edge){v,head[u]};
  18. head[u] = dt;
  19. }
  20. void dfs(int u)
  21. {
  22. sz[u] = ;
  23. for(int i = head[u];i;i = edge[i].nex)
  24. {
  25. if(sz[edge[i].to])continue;
  26. dep[edge[i].to] = dep[u] + ;
  27. fa[edge[i].to] = u;
  28. dfs(edge[i].to);
  29. sz[u] += sz[edge[i].to];
  30. if(sz[hson[u]] < sz[edge[i].to])hson[u] = edge[i].to;
  31. }
  32. }
  33. void dfs(int u,int tp)
  34. {
  35. top[u] = tp;id[u] = ++tot;
  36. if(hson[u])dfs(hson[u],tp);
  37. for(int i = head[u];i;i = edge[i].nex)
  38. if(!id[edge[i].to])dfs(edge[i].to,edge[i].to);
  39. head[u] = ;
  40. }
  41. int lca(int u,int v)
  42. {
  43. while(top[u] != top[v])
  44. {
  45. if(dep[top[u]] < dep[top[v]])swap(u,v);
  46. u = fa[top[u]];
  47. }
  48. return dep[u] < dep[v] ? u : v;
  49. }
  50. bool cmp(int x,int y){return id[x] < id[y];}
  51. void dp(int u)
  52. {
  53. sz[u] = g[u];mx[u] = ;mi[u] = inf;f[u] = ;
  54. for(int i = head[u];i;i = edge[i].nex)
  55. {
  56. int w = dep[edge[i].to] - dep[u];
  57. dp(edge[i].to);sz[u] += sz[edge[i].to];
  58. ans1 = min(ans1,mi[u] + mi[edge[i].to] + w);mi[u] = min(mi[u],mi[edge[i].to] + w);
  59. ans2 = max(ans2,mx[u] + mx[edge[i].to] + w);mx[u] = max(mx[u],mx[edge[i].to] + w);
  60. f[u] += f[edge[i].to] + 1LL * sz[edge[i].to] * (k - sz[edge[i].to]) * w;
  61. }
  62. if(g[u])ans1 = min(ans1,mi[u]),ans2 = max(ans2,mx[u]),mi[u] = ;
  63. head[u] = g[u] = ;
  64. }
  65. void solve()
  66. {
  67. scanf("%d",&k);int top,gr;ans1 = inf;top = dt = ans2 = ;ans1 = inf;
  68. for(int i = ;i <= k;i++)scanf("%d",&a[i]),g[a[i]] = ;
  69. sort(a + ,a + k + ,cmp);
  70. for(int i = ;i <= k;i++)
  71. {
  72. if(!top){que[++top] = a[i];continue;}
  73. gr = lca(que[top],a[i]);
  74. while(id[gr] < id[que[top]])
  75. {
  76. if(id[gr] >= id[que[top - ]])
  77. {
  78. AddEdge(gr,que[top]);
  79. if(que[--top] != gr)que[++top] = gr;
  80. break;
  81. }
  82. AddEdge(que[top - ],que[top]);top--;
  83. }
  84. if(que[top] != a[i])que[++top] = a[i];
  85. }
  86. top--;
  87. while(top)AddEdge(que[top],que[top + ]),top--;
  88. dp(que[]);
  89. printf("%lld %d %d\n",f[que[]],ans1,ans2);
  90. }
  91. int main()
  92. {
  93. scanf("%d",&n);int x,y;
  94. for(int i = ;i < n;i++)
  95. {
  96. scanf("%d %d",&x,&y);
  97. AddEdge(x,y);AddEdge(y,x);
  98. }
  99. dfs();dfs(,);
  100. scanf("%d",&m);
  101. while(m--)solve();
  102. }

[Bzoj3611][Heoi2014]大工程(虚树)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. [BZOJ3611][Heoi2014]大工程

    [BZOJ3611][Heoi2014]大工程 试题描述 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道.  我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上.  在 ...

  9. [BZOJ3611][Heoi2014]大工程(虚树上DP)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 2464  Solved: 1104[Submit][Statu ...

随机推荐

  1. sprintf使用时需要注意的问题

  2. chrome ubuntu启动不了

    安装好后,点击图标没反应 用命令行运行chrome并显示log:google-chrome --enable-logging=stderr --log-level=4 报错如下: 解决:安装更高版本的 ...

  3. Win10 启动64位IE浏览器——修改注册表方法

    修改注册表[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main]下的: "TabProcGrowth"=DWOR ...

  4. Python Syntax Summary

    # _*_ coding: utf-8 _*_ """########################################################## ...

  5. 日常[splay]:水题记——营业额统计

    没错这就是让我深陷splay之中的罪魁祸首,昨天打了一下午结果发现是玄学错误的那个 人生第一棵splay平衡树 题目大意:求一段序列,小于当前元素的最大值和大于当前元素的最小值.从该元素前面的元素找. ...

  6. 关闭Visual Studio 2015 关闭单击打开文件的功能

    工具-->选项-->环境-->选项卡和窗口-->预览选项卡 去掉“在解决方案资源管理器中预览选定的文件(在按住Alt的同时单击可避免预览)(X)”的勾选

  7. 数论基础之组合数&计数问题

    一.组合数:问题引入:现在有 n 个球,取其中的 k 个球,问一共有多少种方式?答案: 公式直观解释:我们考虑有顺序地取出 k 个球:第一次有 n 种选择,第二次有 n-1 种选择,...,第 k 次 ...

  8. DNS域名系统

    1. 什么是DNS? DNS是域名系统的缩写,DNS通过将域名与实际的Web服务器连接来帮助引导Internet上的流量.从本质上讲,它需要一个人性化的请求 – 像simcf.cc这样的域名 – 并将 ...

  9. (10) openssl dhparam(密钥交换)

    openssl dhparam用于生成和管理dh文件.dh(Diffie-Hellman)是著名的密钥交换协议,或称为密钥协商协议,它可以保证通信双方安全地交换密钥. 但注意,它不是加密算法,所以不提 ...

  10. c++_加法变乘法

    加法变乘法 我们都知道:1+2+3+ ... + 49 = 1225现在要求你把其中两个不相邻的加号变成乘号,使得结果为2015 比如:1+2+3+...+10*11+12+...+27*28+29+ ...