题意

题目链接

Sol

比赛结束后才调出来。。不多说啥了,就是因为自己菜。

裸的up-down dp,维护一下一个点上下的直径就行,一开始还想了个假的思路写了半天。。

转移都在代码注释里

毒瘤题目卡空间

#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
#define LL long long
using namespace std;
const int MAXN = 6e5 + 10;
template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;}
template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;}
template <typename A> inline void debug(A a){cout << a << '\n';}
template <typename A> inline LL sqr(A x){return 1ll * x * x;}
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
void print(__int128 x) {
if (x>9) print(x/10);
putchar('0'+x%10);
}
int N, p[MAXN * 2], ve[MAXN * 2];
long long f[MAXN], g[MAXN], mxpre[MAXN], mxsuf[MAXN], dl[MAXN], ul[MAXN];
__int128 ans;
vector<Pair> v[MAXN];
void downdfs(int x, int fa) {
f[x] = dl[x] = 0;
for(auto &tp : v[x]) {
int to = tp.fi, w = tp.se;
if(to == fa) continue;
downdfs(to, x);
chmax(dl[x], f[x] + f[to] + w);
chmax(f[x], f[to] + w);
chmax(dl[x], dl[to]);
}
} void updfs(int x, int fa) {
int cnt = 0;
for(int i = 0; i < v[x].size(); i++)
if(v[x][i].fi != fa) p[++cnt] = v[x][i].fi, ve[cnt] = v[x][i].se; mxpre[0] = 0; mxsuf[cnt + 1] = 0;
for(int i = 1; i <= cnt; i++) mxpre[i] = max(mxpre[i - 1], f[p[i]] + ve[i]);
for(int i = cnt; i >= 1; i--) mxsuf[i] = max(mxsuf[i + 1], f[p[i]] + ve[i]);
//一个点向上的直径:
//1: 从父亲的ul继承过来
//2: 前后缀中的最大值f + 出边 + 入边
//3: 父亲的g + 兄弟节点中最大的f + 出边
//4: 前驱/后继 中的最大和次大
//5: 前驱/后继 中的子树中的直径 for(int i = 1; i <= cnt; i++) {
int to = p[i], w = ve[i];
chmax(g[to], g[x] + w);
chmax(g[to], max(mxpre[i - 1], mxsuf[i + 1]) + w);
chmax(ul[to], ul[x]);//1
chmax(ul[to], mxpre[i - 1] + mxsuf[i + 1]);//2
chmax(ul[to], g[x] + max(mxpre[i - 1], mxsuf[i + 1]));//3
} long long mx1 = -1e18, mx2 = -1e18, mx3 = -1e18;
for(int i = 1; i <= cnt; i++) {
chmax(ul[p[i]], max(mx1 + mx2, mx3)); int tmp = f[p[i]] + ve[i];
if(tmp > mx1) chmax(mx2, mx1), mx1 = tmp;
else if(tmp > mx2) mx2 = tmp;
chmax(mx3, dl[p[i]]);
}
mx1 = -1e18, mx2 = -1e18, mx3 = -1e18;
for(int i = cnt; i >= 1; i--) {
chmax(ul[p[i]], max(mx1 + mx2, mx3)); int tmp = f[p[i]] + ve[i];
if(tmp > mx1) chmax(mx2, mx1), mx1 = tmp;
else if(tmp > mx2) mx2 = tmp;
chmax(mx3, dl[p[i]]);
} for(int i = 0; i < v[x].size(); i++)
if(v[x][i].fi != fa) updfs(v[x][i].fi, x); }
signed main() {
//freopen("a.in", "r", stdin);
N = read();
for(int i = 1; i <= N - 1; i++) {
int x = read(), y = read(), w = read();
v[x].push_back(MP(y, w));
v[y].push_back(MP(x, w));
}
downdfs(1, 0);
updfs(1, 0);
for(int i = 2; i <= N; i++) chmax(ans, (__int128) dl[i] * ul[i]); for(int i = 1; i <= N; i++) for(auto &tp : v[i]) tp.se = -tp.se;
memset(ul, 0, sizeof(ul));
memset(g, 0, sizeof(g));
downdfs(1, 0);
updfs(1, 0);
for(int i = 2; i <= N; i++) chmax(ans, (__int128) dl[i] * ul[i]);
print(ans);
//cout << ans;
return 0;
}

51nod"省选"模测 A 树的双直径(树形dp)的更多相关文章

  1. 51nod“省选”模测第二场 C 小朋友的笑话(线段树 set)

    题意 题目链接 Sol 直接拿set维护\(li\)连续段.因为set内的区间互不相交,而且每个线段会被至多加入删除一次,所以复杂度是对的. #include<bits/stdc++.h> ...

  2. 51nod“省选”模测第二场 B 异或约数和(数论分块)

    题意 题目链接 Sol 这题是来搞笑的吧.. 考虑一个数的贡献是\(O(\frac{N}{i})\) 直接数论分块. #include<bits/stdc++.h> #define Pai ...

  3. bzoj 3302&2447&2103 树的双中心 树形DP

    题目: 题解: bzoj 3302 == 2447 == 2103 三倍经验 首先我们考虑枚举两个中心的位置,然后统计答案. 我们发现,一定有一部分点离第一个中心更近,另一部分点离第二个中心更近 如果 ...

  4. 51nod 1812 树的双直径 题解【树形DP】【贪心】

    老了-稍微麻烦一点的树形DP都想不到了. 题目描述 给定一棵树,边权是整数 \(c_i\) ,找出两条不相交的链(没有公共点),使得链长的乘积最大(链长定义为这条链上所有边的权值之和,如果这条链只有 ...

  5. [CEOI2007]树的匹配Treasury(树形DP+高精)

    题意 给一棵树,你可以匹配有边相连的两个点,问你这棵树的最大匹配时多少,并且计算出有多少种最大匹配. N≤1000,其中40%的数据答案不超过 108 题解 显然的树形DP+高精. 这题是作为考试题考 ...

  6. Codeforces 633F 树的直径/树形DP

    题意:有两个小孩玩游戏,每个小孩可以选择一个起始点,并且下一个选择的点必须和自己选择的上一个点相邻,问两个选的点权和的最大值是多少? 思路:首先这个问题可以转化为求树上两不相交路径的点权和的最大值,对 ...

  7. 2014 Super Training #9 E Destroy --树的直径+树形DP

    原题: ZOJ 3684 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3684 题意: 给你一棵树,树的根是树的中心(到其 ...

  8. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  9. BZOJ5123 线段树的匹配(树形dp)

    线段树的任意一棵子树都相当于节点数与该子树相同的线段树.于是假装在树形dp即可,记忆化搜索实现,有效状态数是logn级别的. #include<iostream> #include< ...

随机推荐

  1. 第68节:Java中的MYSQL运用从小白到大牛

    第68节:Java中的MYSQL运用从小白到大牛 前言 学习java必备要求,学会运用!!! 常见关系化数据库 BootStrap是轻量级开发响应式页面的框架,全局css组件,js插件.栅格系统是将页 ...

  2. springboot动态修改日志级别+权限认证

    1. springboot动态修改日志级别+权限认证 1.1. 需求 网上找到的动态修改日志级别的方式,基本都是没有权限验证的,或者特地关闭权限验证,但也没给出加上验证的解决方式 修改日志等级也是一个 ...

  3. 为什么 array.foreach 不支持 async/await

    一.背景 react 项目中,渲染组件时,显示的数据一直有问题,本来以为是 react 组件的问题,后来才发现罪魁祸首在 fetch 数据的过程,因为我用了 async/await ,而却搭配了 fo ...

  4. 2,linux入门到上手-ssh安装配置及虚拟机基本使用

    ssh配置 1,打开"终端窗口",输入 "sudo apt-get update" --> 回车 --> "输入当前登录用户的管理员密码& ...

  5. 使用一年ESB感受

    ESB(Enterprise service bus)-----企业服务总线的简写. 目前使用的是openESB,Sun公司的开源社区提供的,集成在netbean中,使用glassFish服务器. 先 ...

  6. rest-framework之认证组件

    认证组件 认证简介 作用:校验是否登录 首先定义一个类,集成BaseAuthentication,写一个方法:authenticate,在方法内部,实证过程,认证通过,返回None或者两个对象(use ...

  7. 解决 .NET Core 在 Linux 下的时区问题

    环境 # dotnet --info .NET Core SDK (reflecting any global.json): Version: Commit: 8a7ff6789d Runtime E ...

  8. 开始翻译Disruptor

    刚开始接触Disruptor,看了作者的博客,发现这个大牛很与众不同,他不仅讲解自己的框架的设计思想,还深度介绍了这样设计的原因,其知识范围涵盖了操作系统.数据结构.计算机组成,很有学习的价值.网上有 ...

  9. 【InfluxDB】InfluxDB学习实践笔记

    InfluxDB是用Go编写的一个开源分布式时序.事件和指标数据库,无需外部依赖.它与Elasticsearch.Graphite等类似.比较适用于与事件紧密相关的数据,例如实时日志数据.实时监控数据 ...

  10. [转]Memcache的使用和协议分析详解

    Memcache是什么 Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力. 它可以应 ...