题意

求仙人掌的直径(相距最远的两个点的距离)。

\(n\le 5\times 10^4​\)

分析

  • 建立圆方树,讨论答案路径的 lca 在圆点还是方点。
  • 利用树形 dp 求出每个圆点到 不同子树内圆点 的最长距离与次长距离 \(f_{i,0},f_{i,1}\)。
  • 如果答案以某个圆点作为 lca,答案是 \(f_{i,0}+f_{i,1}\) 。
  • 否则,将一个方点的圆点子节点拿出来,倍长链后利用单调队列找到最优的两个圆点即可。
  • 复杂度 \(O(n)​\) 。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define pb push_back
#define re(x) memset(x, 0, sizeof x)
inline int gi() {
int x = 0,f = 1;
char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) { x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
return x * f;
}
template <typename T> inline bool Max(T &a, T b){return a < b ? a = b, 1 : 0;}
template <typename T> inline bool Min(T &a, T b){return a > b ? a = b, 1 : 0;}
const int N = 1e5 + 7;
int n, m, edc, dfn, tp, ndc, ans;
int low[N], pre[N], stk[N], f[N][2], head[N];
vector<int>G[N];
struct edge {
int lst, to;
edge(){}edge(int lst, int to):lst(lst), to(to){}
}e[N << 1];
void Add(int a, int b) {
e[++edc] = edge(head[a], b), head[a] = edc;
e[++edc] = edge(head[b], a), head[b] = edc;
}
void tarjan(int u, int fa) {
low[u] = pre[u] = ++dfn;
stk[++tp] = u;
go(u)if(v ^ fa) {
if(!low[v]) {
tarjan(v, u);
Min(pre[u], pre[v]);
if(pre[v] >= low[u]) {
G[u].pb(++ndc);
for(int x = -1; x ^ v; )
G[ndc].pb(x = stk[tp--]);
}
}else Min(pre[u], low[v]);
}
}
void dfs(int u, int fa) {
if(u <= n) {
for(int i = 0; i < G[u].size(); ++i) dfs(G[u][i], u);
}else {
int res = 0;
for(int i = 0, len = G[u].size(); i < len; ++i) {
int v = G[u][i];
dfs(v, u);
Max(res, f[v][0] + min(i + 1, len - i));
}
if(res > f[fa][0]) {
f[fa][1] = f[fa][0];
f[fa][0] = res;
}else Max(f[fa][1], res);
}
}
int q[N], val[N];
int main() {
n = gi(), m = gi();ndc = n;
rep(i, 1, m) {
int k = gi(), lst = gi();
rep(j, 2, k) {
int x = gi();
Add(x, lst);
lst = x;
}
}
tarjan(1, 0);
dfs(1, 0);
rep(i, 1, n) Max(ans, f[i][0] + f[i][1]);
rep(i, n + 1, ndc) {
int gg = G[i].size();
G[i].pb(0);
for(int j = 0; j < gg; ++j) G[i].pb(G[i][j]);
int hd = 1, tl = 0, len = (gg + 1) / 2;
for(int j = 0; j < G[i].size(); ++j) {
if(j == gg) continue;
int x = G[i][j];
for(; hd <= tl && q[hd] < j - len; ++hd);
if(hd <= tl) Max(ans, f[x][0] + val[hd] + j);
for(; hd <= tl && f[x][0] - j >= val[tl]; --tl);
q[++tl] = j, val[tl] = f[x][0] - j;
}
}
printf("%d\n", ans);
return 0;
}

[SHOI2008]cactus仙人掌图[圆方树+树dp]的更多相关文章

  1. BZOJ1023:[SHOI2008]cactus仙人掌图(圆方树,DP,单调队列)

    Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus). 所谓简单回路就是指在图上不重复经过任何一个顶点 ...

  2. bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列

    1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1141  Solved: 435[Submit][ ...

  3. bzoj千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图

    http://www.lydsy.com/JudgeOnline/problem.php?id=1023 dp[x] 表示以x为端点的最长链 子节点与x不在同一个环上,那就是两条最长半链长度 子节点与 ...

  4. SHOI2008 cactus仙人掌图 和 UOJ87 mx的仙人掌

    cactus仙人掌图 题目描述 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一 ...

  5. 【BZOJ】1023: [SHOI2008]cactus仙人掌图 静态仙人掌(DFS树)

    [题意]给定仙人掌图(每条边至多在一个简单环上),求直径(最长的点对最短路径).n<=50000,m<=10^7. [算法]DFS树处理仙人掌 [题解]参考:仙人掌相关问题的处理方法(未完 ...

  6. [SHOI2008]cactus仙人掌图

    [题目描述] 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路. 举例 ...

  7. BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌)

    Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的 ...

  8. bzoj1023: [SHOI2008]cactus仙人掌图

    学习了一下圆方树. 圆方树是一种可以处理仙人掌的数据结构,具体见这里:http://immortalco.blog.uoj.ac/blog/1955 简单来讲它是这么做的:用tarjan找环,然后对每 ...

  9. 1023: [SHOI2008]cactus仙人掌图 - BZOJ

    Description如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路 ...

随机推荐

  1. java代码代替xml实现图片

    1.使用StateListDrawable替换selector public static StateListDrawable getSelector(Drawable normalDrawable, ...

  2. (网页)12种不宜使用的Javascript语法(转)

    转自阮一峰: 最近写的一些小东西,总是出各种各样的问题,用了angular.js反应居然比我的jQuery还慢,客户吐槽了,我又把一个小操作,改成了jQuery.浏览一下大神的的博客.转载一点东西: ...

  3. [20170904]11Gr2 查询光标为什么不共享脚本.txt

    [20170904]11Gr2 查询光标为什么不共享脚本.txt --//参考链接下面的注解脚本:https://carlos-sierra.net/2017/09/01/poors-man-scri ...

  4. python第十七天---时间模块、random模块

    作完一个作业,开始新的学习: 有由今天的时间有限所有学习了以下两个模块,明天继续! 时间模块.random模块 import time #!usr/bin/env python #-*-coding: ...

  5. MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化

    MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...

  6. 鸟哥的 Linux 私房菜Shell Scripts篇(一)

    参考: http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script_be http://www.runoob.com/lin ...

  7. 3.8Python数据处理篇之Numpy系列(八)---Numpy的梯度函数

    目录 目录 前言 (一)函数说明 (二)一维数组的应用 (三)多维数组的应用 目录 前言 梯度函数,其中的梯度也就是斜率,反映的是各个数据的变化率.在numpy中只有一个梯度函数. (一)函数说明 ( ...

  8. LInux下(centos7.2)更新 python3.7

    进入超级管理员目录  su root 下载 wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz 找到下载的文件解压  tar - ...

  9. nginx 了解一下

    先决条件 想要流畅的配置 nginx 需要了解一下内容: 1.nginx 调用方式: 启动 (双击 exe.cmd start nginx .cmd nginx) 使用 (powershell 调用需 ...

  10. January 03rd, 2018 Week 01st Wednesday

    My existence is not without reason. I know that I could be a quite a different person. 我的存在必定有意义,我知道 ...