SPOJ6717 Two Paths 树形dp

首先有朴素的\(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的更多相关文章
- 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 ...
- 牛客第八场 C-counting paths 树形dp计数
题目地址 题意 给你一颗树 初始点颜色全部为白色 对于每一个满足要求一的点集s f(s)的定义为先把点集内的点染黑 满足要求二的路径集合数量 要求一为两两黑点之间不能出现白色的点 要求二为将这个路径集 ...
- 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 ...
- HDU4003Find Metal Mineral[树形DP 分组背包]
Find Metal Mineral Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Other ...
- 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 ...
- hdu 4003 Find Metal Mineral 树形DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003 Humans have discovered a kind of new metal miner ...
- poj3162(树形dp+优先队列)
Walking Race Time Limit: 10000MS Memory Limit: 131072K Total Submissions: 5409 Accepted: 1371 Ca ...
- POJ 3162.Walking Race 树形dp 树的直径
Walking Race Time Limit: 10000MS Memory Limit: 131072K Total Submissions: 4123 Accepted: 1029 Ca ...
- HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca
Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...
随机推荐
- Python练习-有点儿意思的用户登录
Alex大神的需求(说实话他需求真特么多,真难满足他): 编写一个用户登陆接口:输入用户名密码,认证成功后显示欢迎信息,输错三次后锁定; # 编辑者:闫龙 #用户登录功能输入3次以上会被锁定:为了方便 ...
- css 实现圆形头像
1.方法一 直接设置img为圆形,这种情况下如果图片不是正方形,图片会被拉伸 <img class="circleImg" src="../img/photo/im ...
- web项目打包后在代码中获取资源文件
在web项目里面,有时代码里面需要引用一些自定义的配置文件,这些配置文件如果放在类路径下,项目经过打包后使用的相对路径也会发生变化,所以以下给出了三种解决方案. 一.properties下配置 在类路 ...
- linux挂载光盘
1.找到光盘的位置 ls -l /dev |grep cdrom mount /dev/sr0 /mnt [root@node2 /]# ls -l /dev |grep cdrom lrwxrwx ...
- 虚拟环境pipenv的使用
安装虚拟环境 安装python3.6 python -m site --user-base 找到 用户基础目录 指定python版本的方式 pipenv --python 3.8 安装 用户范围内安装 ...
- jQuery简单介绍
一.jQuery介绍 jQuery是一个轻量级的.兼容多浏览器的JavaScript库. jQuery使用户能够更方便地处理HTML Document.Events.实现动画效果.方便地进行Ajax交 ...
- python-windows下将单个py文件生成exe
突然要生成一个exe给其他人用.紧急搜索下了 命令行参数获取用如下方法 from sys import argv base64path = argv[1] argv这个元组就是你的参数列表了,同C一样 ...
- Java内存优化和性能优化的几点建议
1.没有必要时请不用使用静态变量 使用Java的开发者都知道,当某个对象被定义为stataic变量所引用,这个对象所占有的内存将不会被回收.有时,开发者会将经常调用的对象或者变量定义为static,以 ...
- 关于主键的设计、primary key
主键:用于唯一标识一个表中一行数据. 外键:用于建立两个表之间的关系,A表中有一列是B表中的主键,那么A表中这列的数据就受到B表主键的约束. 那么关于主键应该如何设计呢,这里我说下优缺点: 1.用自动 ...
- CF614A 【Link/Cut Tree】
题意:求出所有w^i使得l<=w^i<=r 输入为一行,有三个数,分别是l,r,w.意义如题目所描述 输出为一行,输出所有满足条件的数字,每两个数字中间有一个空格 如果没有满足条件的数字则 ...