题意

题目链接

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. while(true)应用之 实现自己的消息队列

    早些时候,一直有个疑问,就是比如你从前端发一个操作之后,后台为什么能够及时处理你的东西呢?当然了,我说的不是,服务器为什么能够立即接收到你的请求之类高大上的东西.而是,假设你用异步去做一个事情,而后台 ...

  2. ubuntu下opencv的版本切换及遇到的问题解决

    默认使用opencv 3.2的时候,使用SVM的时候,系统报错如下: error: ‘class MySVM’ has no member named ‘decision_func’ 解决方法:要把系 ...

  3. 用python自制微信机器人,定时发送天气预报

    0 引言 前段时间找到了一个免费的天气预报API,费了好段时间把这个API解析并组装成自己想用的格式了,就想着如何实现每天发送天气信息给自己.最近无意中发现了wxpy库,用它来做再合适不过了.以下是w ...

  4. promise与async-await

    一. async/await 相对 promise 的优势 async/await 拥有更通用的作用域,使得代码有更好的易读性和可维护性. promise 由于其链式调用,每一个函数都有自己的作用域, ...

  5. Git基本命令 -- 别名 + 忽略 + 推送

    别名. 我可以使用这个命令查看repository的历史 git log --all --graph --decorate --oneline: 这个命令可能比较常用, 但是又比较长. 这时我可以创建 ...

  6. Linux编程 9 (shell类型,shell父子关系,子shell用法)

    一. shell类型 1.1  交互式 bin/ shell程序 当用户登录到某个虚拟控制台终端或是在GUI中启动终端仿真器时,默认的shell程序就会开始运行.系统启动什么样的shell程序取决于你 ...

  7. Java IO API记录

    文件路径: public static final String FILEPATH= File.separator+"Users"+ File.separator+"xu ...

  8. MySQL批量插入数据的几种方法

    最近公司要求测试数据库的性能,就上网查了一些批量插入数据的代码,发现有好几种不同的用法,插入同样数据的耗时也有区别 别的先不说,先上一段代码与君共享 方法一: package com.bigdata; ...

  9. 【转载】uCOS系统的思考

    一:  世界潮流,浩浩汤汤,顺之者昌,逆之者亡---孙中山 从80X86到ARM9,再从ARM9到ARM7,平台是越做越简单,但是简单并不是意味着退步,反而是种潮流趋势... 在CISC道路上渐行渐远 ...

  10. golang的字符串拼接

    常用拼接方法 字符串拼接在日常开发中是很常见的需求,目前有两种普遍做法: 一种是直接用 += 来拼接 s1 := "Hello" s2 := "World" s ...