Manthan, Codefest 16 F
寻找树上最大权值和的两条不相交的路径。
树形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的更多相关文章
- Manthan, Codefest 16
暴力 A - Ebony and Ivory import java.util.*; import java.io.*; public class Main { public static void ...
- CF Manthan, Codefest 16 G. Yash And Trees 线段树+bitset
题目链接:http://codeforces.com/problemset/problem/633/G 大意是一棵树两种操作,第一种是某一节点子树所有值+v,第二种问子树中节点模m出现了多少种m以内的 ...
- Manthan, Codefest 16 H. Fibonacci-ish II 大力出奇迹 莫队 线段树 矩阵
H. Fibonacci-ish II 题目连接: http://codeforces.com/contest/633/problem/H Description Yash is finally ti ...
- Manthan, Codefest 16 C. Spy Syndrome 2 字典树 + dp
C. Spy Syndrome 2 题目连接: http://www.codeforces.com/contest/633/problem/C Description After observing ...
- Manthan, Codefest 16 C
建trie树,刚好字符串是反向的,直接在原图上向前搜索就OK了……………… 可怜的我竟然用了RK来hash,在test67那里T了…… 贴个RK的 #include <iostream> ...
- Manthan, Codefest 16 D. Fibonacci-ish
D. Fibonacci-ish time limit per test 3 seconds memory limit per test 512 megabytes input standard in ...
- 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 ...
- Manthan, Codefest 16 -C. Spy Syndrome 2
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
- Manthan, Codefest 16 -A Ebony and Ivory
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
随机推荐
- TensorFlow---image recognition--classify_image运行、文件说明与错误(路径)解决
tutorial系列mnist已经玩过了,这篇玩一下 classify_image,其实就是image label.模型已经训练好的了,直接下载下来在.pb文件中. 本机环境: Win10 + Pyt ...
- MySQL与Sqlserver数据获取
由于项目要求,一个.net mvc登录注册的东西网站必须放弃sqlserver数据去使用MySQL数据库,因此我遇到了一些问题,并找出相应的解决方法, 因为sqlserver跟MySQL的数据引擎不同 ...
- SpringMVC高级课程
requestBody和responseBody requestBody把前台页面传递JSON格式数据强制转换JavaBean responseBody在后台把javabean转换成JSON格式的数据 ...
- IPython、Notebook、qtconsole使用教程
IPython.Notebook.qtconsole使用教程 上一篇为Python,IPython,qtconsole,Notebook,Jupyter快速安装教程 1. 使用IPython 自动补全 ...
- Linux学习日记之crontab使用notify-send实现每小时通知提醒
crontab命令用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行 通过crontab -e 可以打开编辑文件添加新的命令 notif ...
- FTP初始化文件.netrc使用技巧[转发]
FTP初始化文件.netrc使用技巧 FTP(文件传输)和E-mail(电子邮件).Telnet(远程登录)一样,是 Internet的三大主要功能之一.因为使用频繁,用户往往会遇到各种 各样的问题, ...
- AI:IPPR的数学表示-CNN稀疏结构进化(Mobile、xception、Shuffle、SE、Dilated、Deformable)
接上一篇:AI:IPPR的数学表示-CNN基础结构进化(Alex.ZF.Inception.Res.InceptionRes). 抄自于各个博客,有大量修改,如有疑问,请移步各个原文..... 前言 ...
- iOS,Core Animation--负责视图的复合功能
简介 UIKit API UIKit是一组Objective-C API,为线条图形.Quartz图像和颜色操作提供Objective-C 封装,并提供2D绘制.图像处理及用户接口级别的动画. ...
- 导出功能在数据库内容为数字,excel表格中是汉字的时候
代码如下: @ExcelField(title = "饮水器评价",dictType = "waterer_rate" ,align = 2, sort = 2 ...
- CAD控件:COM接口实现自定义实体
1. 实现步骤: 3 1. 实现步骤: 参考例子 :Src\MxDraw5.2\samples\ie\iedemoTest.htm 1) 增加自定义实体对象 调用DrawCustomEntity函数, ...