寻找树上最大权值和的两条不相交的路径。

树形DP题。挺难的,对于我……

定义三个变量ma[MAXN], t[MAXN], sum[MAXN]

其中,ma[i]代表i子树中,最长的路径和

t[i]代表i子树中,用来维护已有一条路径,而且还有一条链从叶子节点到i,则可以从根节点i向上扩展。如下图,维护红色部分

sum[i]维护从某叶子节点到根节点i的最长路径。

转移方程可以看代码,很容易明白

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <set>
  7. #define LL long long
  8.  
  9. using namespace std;
  10.  
  11. const int MAXN = 100050;
  12. const int MOD = 1e9 + 7;
  13.  
  14. LL ans;
  15. LL ma[MAXN], t[MAXN], sum[MAXN];
  16. LL l[MAXN], ml[MAXN], r[MAXN], mr[MAXN];
  17. bool leaf[MAXN];
  18. LL mm[10];
  19. bool vis[MAXN];
  20. int head[MAXN];
  21. struct Edge{
  22. int u, v;
  23. int next;
  24. }edge[MAXN * 2];
  25. int weight[MAXN], par[MAXN];
  26. int n, tot;
  27.  
  28. void addedge(int u, int v){
  29. edge[tot].u = u;
  30. edge[tot].v = v;
  31. edge[tot].next = head[u];
  32. head[u] = tot++;
  33. }
  34.  
  35. void dfs(int u){
  36. vis[u] = true;
  37. leaf[u] = true;
  38. for(int e = head[u]; e != -1; e = edge[e].next){
  39. int v = edge[e].v;
  40. if(vis[v]) continue;
  41. par[v] = u;
  42. dfs(v);
  43. leaf[u] = false;
  44. }
  45. }
  46.  
  47. void slove(int u){
  48. if(leaf[u]){
  49. ma[u] = t[u] = sum[u] = weight[u];
  50. return ;
  51. }
  52.  
  53. LL m1, m2, M1, M2;
  54. m1 = m2 = M1 = M2 = 0;
  55. for(int e = head[u]; e != -1; e = edge[e].next){
  56. int v = edge[e].v;
  57. if(v != par[u]){
  58. slove(v);
  59. if(ma[v] >= M1){
  60. M2 = M1, M1 = ma[v];
  61. }
  62. else if(ma[v] > M2){
  63. M2 = ma[v];
  64. }
  65. if(sum[v] >= m1){
  66. m2 = m1, m1 = sum[v];
  67. }
  68. else if(sum[v] > m2){
  69. m2 = sum[v];
  70. }
  71. t[u] = max(t[u], t[v] + weight[u]);
  72. }
  73. }
  74. ma[u] = max(M1, m1 + m2 + weight[u]);
  75. sum[u] = m1 + weight[u];
  76. ans = max(ans, M1 + M2);
  77.  
  78. int counts = 0;
  79. for(int e = head[u]; e != -1; e = edge[e].next){
  80. int v = edge[e].v;
  81. if(v != par[u]){
  82. l[++counts] = sum[v];
  83. r[counts] = sum[v];
  84. }
  85. }
  86. l[0] = ml[0] = r[counts + 1] = mr[counts + 1] = 0;
  87.  
  88. //从左往右寻找最大的两个sum
  89.  
  90. for(int i = 1; i <= counts ; i++){
  91. if(l[i] > l[i - 1]) ml[i] = l[i - 1];
  92. else if(l[i] > ml[i - 1]){
  93. ml[i] = l[i];
  94. l[i] = l[i - 1];
  95. }
  96. else{
  97. l[i] = l[i - 1], ml[i] = ml[i - 1];
  98. }
  99. }
  100.  
  101. //从右往左。。。。
  102.  
  103. for(int i = counts; i >= 1; i--){
  104. if(r[i] > r[i + 1]) mr[i] = r[i + 1];
  105. else if(r[i] > mr[i + 1]){
  106. mr[i] = r[i];
  107. r[i] = r[i + 1];
  108. }
  109. else{
  110. r[i] = r[i + 1], mr[i] = mr[i + 1];
  111. }
  112. }
  113.  
  114. counts = 0;
  115. for(int e = head[u]; e != -1; e = edge[e].next){
  116. int v = edge[e].v;
  117. if(v == par[u]) continue;
  118. counts ++;
  119. mm[0] = l[counts - 1], mm[1] = ml[counts - 1];
  120. mm[2] = r[counts + 1], mm[3] = mr[counts + 1];
  121.  
  122. sort(mm, mm + 4);
  123.  
  124. ans = max(ans, weight[u] + ma[v] + mm[3] + mm[2]);
  125. ans = max(ans, weight[u] + mm[3] + t[v]);
  126. t[u] = max(t[u], ma[v] + weight[u] + mm[3]);
  127. }
  128.  
  129. }
  130.  
  131. int main(){
  132. scanf("%d", &n);
  133. memset(head, -1, sizeof(head));
  134. // memset(vis, false, sizeof(vis));
  135. // memset(leaf, false, sizeof(leaf));
  136. tot = 0;
  137. memset(t, 0, sizeof(t));
  138. for(int i = 1; i <= n; i++){
  139. scanf("%d", &weight[i]);
  140. }
  141. int u, v;
  142. memset(par, -1, sizeof(par));
  143. for(int i = 0; i < n - 1; i++){
  144. scanf("%d%d", &u, &v);
  145. addedge(u, v);
  146. addedge(v, u);
  147. }
  148. dfs(1);
  149. ans = 0;
  150. slove(1);
  151.  
  152. cout << ans << endl;
  153. }

  

Manthan, Codefest 16 F的更多相关文章

  1. Manthan, Codefest 16

    暴力 A - Ebony and Ivory import java.util.*; import java.io.*; public class Main { public static void ...

  2. CF Manthan, Codefest 16 G. Yash And Trees 线段树+bitset

    题目链接:http://codeforces.com/problemset/problem/633/G 大意是一棵树两种操作,第一种是某一节点子树所有值+v,第二种问子树中节点模m出现了多少种m以内的 ...

  3. Manthan, Codefest 16 H. Fibonacci-ish II 大力出奇迹 莫队 线段树 矩阵

    H. Fibonacci-ish II 题目连接: http://codeforces.com/contest/633/problem/H Description Yash is finally ti ...

  4. Manthan, Codefest 16 C. Spy Syndrome 2 字典树 + dp

    C. Spy Syndrome 2 题目连接: http://www.codeforces.com/contest/633/problem/C Description After observing ...

  5. Manthan, Codefest 16 C

    建trie树,刚好字符串是反向的,直接在原图上向前搜索就OK了……………… 可怜的我竟然用了RK来hash,在test67那里T了…… 贴个RK的 #include <iostream> ...

  6. Manthan, Codefest 16 D. Fibonacci-ish

    D. Fibonacci-ish time limit per test 3 seconds memory limit per test 512 megabytes input standard in ...

  7. Manthan, Codefest 16(B--A Trivial Problem)

    B. A Trivial Problem time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  8. Manthan, Codefest 16 -C. Spy Syndrome 2

    time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...

  9. Manthan, Codefest 16 -A Ebony and Ivory

    time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...

随机推荐

  1. [转]URL最大长度问题

    本文转自:http://www.cnblogs.com/henryhappier/archive/2010/10/09/1846554.html 今天在测试Email Ticket的时候发现在进行Ma ...

  2. 浅谈css的行内类型标签和块级标签

    常用标签的行内类型标签有:a.span.img:块级标签有:div.p.h1~6.ul.ol.li.dl.dt.dd. 行内类型标签的特征:标签的大小由标签的内容决定,不能设置width和height ...

  3. Greenplum开发

    Greenplum(GP)采用了MPP架构,基于开源的数据库 PostgreSQL(PG). 1.首先什么是MPP架构? GreenPlum的架构采用了MPP(大规模并行处理).在 MPP 系统中,每 ...

  4. SQL server 上机练习题

    首先创建一个数据库,里面有 登录表 学生表   课程表   选课表 成绩表 1. 查询Student表中的所有记录的Sname.Ssex和Class列.2. 查询教师所有的单位即不重复的Depart列 ...

  5. 并发编程学习笔记(8)----ThreadLocal的使用及源码分析

    1. ThreadLocal的理解 ThreadLocal,顾名思义,就是线程的本地变量,ThreadLocal会为每个线程创建一个本地变量副本,使得使用ThreadLocal管理的变量在多线程的环境 ...

  6. 扩增子分析解读4去嵌合体 非细菌序列 生成代表性序列和OTU表

    本节课程,需要先完成 扩增子分析解读1质控 实验设计 双端序列合并 2提取barcode 质控及样品拆分 切除扩增引物 3格式转换 去冗余 聚类   先看一下扩增子分析的整体流程,从下向上逐层分析 分 ...

  7. MySQL单表数据不超过500万:是经验数值,还是黄金铁律?

    今天,探讨一个有趣的话题:MySQL 单表数据达到多少时才需要考虑分库分表?有人说 2000 万行,也有人说 500 万行.那么,你觉得这个数值多少才合适呢? 曾经在中国互联网技术圈广为流传着这么一个 ...

  8. CAD梦想看图6.0安卓版 20181022更新

    下载地址: http://www.mxdraw.com/ndetail_10109.html 1. 保存上次的文件浏览位置和绘制颜色 2. 调整工具条按钮位置和文字 3. 增加测量距离和面积时的捕捉功 ...

  9. 01C++编辑编译运行环境

    C++编辑编译运行环境 Bloodshed Dev-C++ Microsoft Visual Studio

  10. kvm--virsh命令行下管理虚拟机

    virsh 既有命令行模式,也有交互模式,在命令行直接输入 virsh 就进入交互模式, virsh 后面跟命令参数,则是命令行模式: (1)基础操作 --- 命令行下管理虚拟机 virsh list ...