首先有朴素的\(O(n^2)\)想法

首先枚举断边,之后对于断边之后的两棵子树求出直径

考虑优化这个朴素的想法

考虑换根\(dp\)

具体而言,首先求出\(f[i], fs[i]\)表示\(i\)号点向下的最长链以及\(i\)号子树内部最长的直径

并且在求出\(g[i]\)表示\(fa[i]\)在\(i\)号节点子树外的最长链

\(gs[i]\)表示\(i\)号节点子树外的直径

对于所有的\(fs[i] * gs[i]\)取\(max\)即为答案


首先一遍\(dfs\)把\(f, fs\)求出来

考虑怎么求\(gs[o]\),有以下几种可能

  • 一条\(fa[o]\)引申出去的链 + \(fa[o]\) 除了\(o\)子树以外的最长链

  • \(gs[fa]\)

  • 两条\(fa[o]\)除了\(o\)子树以外的链的和

用前缀和后缀来做到删除


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; #define ll long long
#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --) #define tpr template <typename ra>
tpr inline void cmin(ra &a, ra b) { if(a > b) a = b; }
tpr inline void cmax(ra &a, ra b) { if(a < b) a = b; } #define gc getchar
inline int read() {
int p = 0, w = 1; char c = gc();
while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
return p * w;
} const int sid = 200050; ll ans;
int n, cnp;
int cap[sid], nxt[sid], node[sid]; inline void addedge(int u, int v) {
nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v;
} int f[sid], fs[sid];
int g[sid], gs[sid], q[sid], ps[sid], ss[sid]; #define cur node[i]
void dfs1(int o, int fa) {
for(int i = cap[o]; i; i = nxt[i])
if(cur != fa) {
dfs1(cur, o);
cmax(fs[o], fs[cur]);
cmax(fs[o], f[cur] + f[o] + 1);
cmax(f[o], f[cur] + 1);
}
} void dfs2(int o, int fa) { if(!fa) g[o] = -1; int tot = 0;
int sx = 0, mx = 0, px = 0; for(int i = cap[o]; i; i = nxt[i])
if(cur != fa) q[++ tot] = cur; rep(i, 1, tot + 1) ps[i] = ss[i] = 0; rep(i, 1, tot) {
int p = q[i];
cmax(g[p], g[o] + 1);
cmax(g[p], ps[i - 1]);
ps[i] = max(ps[i - 1], f[p] + 1);
} drep(i, tot, 1) {
int p = q[i];
cmax(g[p], ss[i + 1]);
ss[i] = max(ss[i + 1], f[p] + 1);
} rep(i, 1, tot) {
int p = q[i];
cmax(gs[p], ps[i - 1] + ss[i + 1]);
cmax(gs[p], gs[o]);
cmax(gs[p], g[o] + 1 + ps[i - 1]);
cmax(gs[p], g[o] + 1 + ss[i + 1]);
} rep(i, 1, tot) {
int p = q[i];
cmax(gs[p], mx + sx);
cmax(gs[p], px); cmax(px, fs[p]);
if(f[p] + 1 >= mx) sx = mx, mx = f[p] + 1;
else if(f[p] + 1 >= sx) sx = f[p] + 1;
} mx = sx = px = 0; drep(i, tot, 1) {
int p = q[i];
cmax(gs[p], mx + sx);
cmax(gs[p], px); cmax(px, fs[p]);
if(f[p] + 1 >= mx) sx = mx, mx = f[p] + 1;
else if(f[p] + 1 >= sx) sx = f[p] + 1;
} for(int i = cap[o]; i; i = nxt[i])
if(cur != fa) {
cmax(ans, 1ll * fs[cur] * gs[cur]);
dfs2(cur, o);
}
} int main() {
n = read();
rep(i, 2, n) {
int u = read(), v =read();
addedge(u, v); addedge(v, u);
}
dfs1(1, 0); dfs2(1, 0);
printf("%lld\n", ans);
return 0;
}

SPOJ6717 Two Paths 树形dp的更多相关文章

  1. Codeforces Beta Round #14 (Div. 2) D. Two Paths 树形dp

    D. Two Paths 题目连接: http://codeforces.com/contest/14/problem/D Description As you know, Bob's brother ...

  2. 牛客第八场 C-counting paths 树形dp计数

    题目地址 题意 给你一颗树 初始点颜色全部为白色 对于每一个满足要求一的点集s f(s)的定义为先把点集内的点染黑 满足要求二的路径集合数量 要求一为两两黑点之间不能出现白色的点 要求二为将这个路径集 ...

  3. Codeforces Beta Round #14 (Div. 2) Two Paths (树形DP)

    Two Paths time limit per test 2 seconds memory limit per test 64 megabytes input standard input outp ...

  4. HDU4003Find Metal Mineral[树形DP 分组背包]

    Find Metal Mineral Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Other ...

  5. CF 337D Book of Evil 树形DP 好题

    Paladin Manao caught the trail of the ancient Book of Evil in a swampy area. This area contains n se ...

  6. hdu 4003 Find Metal Mineral 树形DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003 Humans have discovered a kind of new metal miner ...

  7. poj3162(树形dp+优先队列)

    Walking Race Time Limit: 10000MS   Memory Limit: 131072K Total Submissions: 5409   Accepted: 1371 Ca ...

  8. POJ 3162.Walking Race 树形dp 树的直径

    Walking Race Time Limit: 10000MS   Memory Limit: 131072K Total Submissions: 4123   Accepted: 1029 Ca ...

  9. HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca

    Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...

随机推荐

  1. VMware虚拟机 安装centos7并设置静态ip 连接外网

    首先下载VMware虚拟机:http://xzc.197746.com/VMware-Workstation-12.5.9.zip 然后下载centos7镜像:http://vault.centos. ...

  2. Strusts2笔记9--防止表单重复提交和注解开发

    防止表单重复提交: 用户可能由于各种原因,对表单进行重复提交.Struts2中使用令牌机制防止表单自动提交.以下引用自北京动力节点:

  3. Linux信息搜集

    ## 1.取证工具 - LiME 内存获取工具 - volatility 内存分析工具 ## 2.机器信息收集 #sysinfo 16 # # 查看当前登录用户 who > who.txt # ...

  4. collision

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAd0AAACYCAIAAAAuvaRSAAAAA3NCSVQICAjb4U/gAAAgAElEQVR4Xu

  5. 【转】GridView 加载空行并点击编辑每一个单元格

    代码 <script runat="server"> protectedvoid Button1_Click(object sender, System.EventAr ...

  6. openstack发展历程及其架构简介

    1.0 Openstack介绍 OpenStack既是一个社区,也是一个项目和一个开源软件,它提供了一个部署云的操作平台或工具集.其宗旨在于,帮助组织运行为虚拟计算或存储服务的云,为公有云.私有云,也 ...

  7. MySQL 导入CSV数据

    第一步 创建表结构 create table t1( key1 ), v1 ) ); 第二步 导入数据 load data local infile 'D:/t1.csv' into table t1 ...

  8. No.18 selenium学习之路之批量执行测试用例

    diascover方法,加载所有测试用例 1.discover方法里面有三个参数: -case_dir:测试用例的目录 -pattern:这个是匹配脚本名称的规则,test*.py意思是匹配test开 ...

  9. 洛谷P2018消息传递

    传送门啦 这个树形dp就没那么简单了,运用了一下贪心的思想 不同的排序方法对应着不同的转移方程,如果我们用 $ f[x] = max(f[x] , b[i] +cnt - i + 1) $ 来进行转移 ...

  10. FZU 1901 Period II(KMP循环节+公共前后缀)

    题目链接:http://acm.fzu.edu.cn/problem.php?pid=1901 题目大意:题目大意求出所有p满足s[i]=s[i+p](i<=len-p) 解题思路: 其实就是要 ...