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

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

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

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

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

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

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

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
#define LL long long using namespace std; const int MAXN = 100050;
const int MOD = 1e9 + 7; LL ans;
LL ma[MAXN], t[MAXN], sum[MAXN];
LL l[MAXN], ml[MAXN], r[MAXN], mr[MAXN];
bool leaf[MAXN];
LL mm[10];
bool vis[MAXN];
int head[MAXN];
struct Edge{
int u, v;
int next;
}edge[MAXN * 2];
int weight[MAXN], par[MAXN];
int n, tot; void addedge(int u, int v){
edge[tot].u = u;
edge[tot].v = v;
edge[tot].next = head[u];
head[u] = tot++;
} void dfs(int u){
vis[u] = true;
leaf[u] = true;
for(int e = head[u]; e != -1; e = edge[e].next){
int v = edge[e].v;
if(vis[v]) continue;
par[v] = u;
dfs(v);
leaf[u] = false;
}
} void slove(int u){
if(leaf[u]){
ma[u] = t[u] = sum[u] = weight[u];
return ;
} LL m1, m2, M1, M2;
m1 = m2 = M1 = M2 = 0;
for(int e = head[u]; e != -1; e = edge[e].next){
int v = edge[e].v;
if(v != par[u]){
slove(v);
if(ma[v] >= M1){
M2 = M1, M1 = ma[v];
}
else if(ma[v] > M2){
M2 = ma[v];
}
if(sum[v] >= m1){
m2 = m1, m1 = sum[v];
}
else if(sum[v] > m2){
m2 = sum[v];
}
t[u] = max(t[u], t[v] + weight[u]);
}
}
ma[u] = max(M1, m1 + m2 + weight[u]);
sum[u] = m1 + weight[u];
ans = max(ans, M1 + M2); int counts = 0;
for(int e = head[u]; e != -1; e = edge[e].next){
int v = edge[e].v;
if(v != par[u]){
l[++counts] = sum[v];
r[counts] = sum[v];
}
}
l[0] = ml[0] = r[counts + 1] = mr[counts + 1] = 0; //从左往右寻找最大的两个sum for(int i = 1; i <= counts ; i++){
if(l[i] > l[i - 1]) ml[i] = l[i - 1];
else if(l[i] > ml[i - 1]){
ml[i] = l[i];
l[i] = l[i - 1];
}
else{
l[i] = l[i - 1], ml[i] = ml[i - 1];
}
} //从右往左。。。。 for(int i = counts; i >= 1; i--){
if(r[i] > r[i + 1]) mr[i] = r[i + 1];
else if(r[i] > mr[i + 1]){
mr[i] = r[i];
r[i] = r[i + 1];
}
else{
r[i] = r[i + 1], mr[i] = mr[i + 1];
}
} counts = 0;
for(int e = head[u]; e != -1; e = edge[e].next){
int v = edge[e].v;
if(v == par[u]) continue;
counts ++;
mm[0] = l[counts - 1], mm[1] = ml[counts - 1];
mm[2] = r[counts + 1], mm[3] = mr[counts + 1]; sort(mm, mm + 4); ans = max(ans, weight[u] + ma[v] + mm[3] + mm[2]);
ans = max(ans, weight[u] + mm[3] + t[v]);
t[u] = max(t[u], ma[v] + weight[u] + mm[3]);
} } int main(){
scanf("%d", &n);
memset(head, -1, sizeof(head));
// memset(vis, false, sizeof(vis));
// memset(leaf, false, sizeof(leaf));
tot = 0;
memset(t, 0, sizeof(t));
for(int i = 1; i <= n; i++){
scanf("%d", &weight[i]);
}
int u, v;
memset(par, -1, sizeof(par));
for(int i = 0; i < n - 1; i++){
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
dfs(1);
ans = 0;
slove(1); cout << ans << endl;
}

  

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. Ant安装以及环境配置以及使用[windows环境]

    一.安装ant 官方主页http://ant.apache.org下载新版的ant. *下载对应的版本,解压到我们的硬盘. 二.配置环境变量 Window中设置ant环境变量: ANT_HOME    ...

  2. SqlServer数据库(可疑)解决办法

    -- 当数据库发生这种操作故障时,可以按如下操作步骤可解决此方法,打开数据库里的Sql 查询编辑器窗口,运行以下的命令. --1.修改数据库为紧急模式 ALTER DATABASE Zhangxing ...

  3. .Net实战之反射外卖计费

    场景 叫外卖支付,可以有以下优惠: 1.  满30元减12 2.  是会员减配送费,比如5元 3.  优惠券 …. 问题? 如何在不改代码的情况下更灵活的去控制优惠的变化??? 有些代码与实际业务可能 ...

  4. EditPlus里面自带有更改文件编码的功能

  5. python自动化--语言基础线程、生产者消费者示例

    进程与线程的区别:进程不共享空间,线程共享地址空间 线程共享空间优缺点:优点:多线程给用户的体验好些,打开时占用的内存比进程少缺点:共享地址空间会相互干扰,甚至有影响 import threading ...

  6. 微信小程序组件解读和分析:五、text文本

    text文本组件说明: text 文本就是微信小程序中显示出来的文本. text文本组件的示例代码运行效果如下: 下面是WXML代码: [XML] 纯文本查看 复制代码 ? 1 2 3 4 <v ...

  7. 第一次创建svn的项目的使用方法

    1.第一步.在服务器上创建svn项目,将开发人人员你的账号密码添加上去. 2.第二步.开始在本地创建一个文件夹,点文件夹,右键->tortoisSVN->repo-brower 填写svn ...

  8. PHPStorm+XDebug进行调试

    笔者的开发环境如下: Windows8.1+Apache+PhpStorm+XDebug+Firefox(XDebug helper 1.4.3插件). 一.XDebug安装配置 (1)下载XDebu ...

  9. QuickClip—界面原型设计

    1.需不需要设置用户登录/注册页? QuickClip没有提供该项功能.因为本产品为单纯的移动端视频编辑软件,是一个工具类软件.而且移动端软件本就追求的是方便快捷.简单易用,本产品不需要标识使用者的身 ...

  10. Python【每日一问】34

    问: 基础题: 定义函数实现以下功能:求出 0-n 所能组成的奇数个数,位数最多 n+1 (0<n<10),比如键盘输入n=7,求出0-7所能组成的奇数个数 提高题: 有如下分数序列: 2 ...