本质上还是树形dp。建立圆方树,遇到圆点的时候直接求(和树形dp一样即可),遇到方点做中转点的时候要考虑会从圆的另一侧通过(需满足最短路径的原则)。原本是对于圆上的点进行 \(n^{2}\) 的匹配,果断超时。但没有发现 \(n ^ {2}\) 的dp明显是一个可以单调队列优化的dp。所以在遇上难解决的问题的时候,一定要融会贯通地思考。有一个细节:将圆复制一下可以去掉 \(max\)造成的影响,dp就十分方便了。

#include <bits/stdc++.h>
using namespace std;
#define maxn 500000
int n, m, N, timer, ans;
int fa[maxn], dfn[maxn], low[maxn];
int f[maxn][], id[maxn], S[maxn];
int tmp[maxn], q[maxn];
int F[maxn][], SS[maxn]; struct edge
{
int cnp, head[maxn], to[maxn], last[maxn], w[maxn];
edge() { cnp = ; }
void add(int u, int v, int ww)
{
to[cnp] = v, last[cnp] = head[u], w[cnp] = ww, head[u] = cnp ++;
to[cnp] = u, last[cnp] = head[v], w[cnp] = ww, head[v] = cnp ++;
}
}E1, E2; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} void Solve(int u, int v)
{
++ N; int ID = , pre = ;
for(int i = v; i != fa[u]; i = fa[i])
S[i] = pre ++, id[i] = ++ ID;
S[N] = S[u], S[u] = ;
for(int i = v; i != fa[u]; i = fa[i])
E2.add(N, i, min(S[i], S[N] - S[i]));
} void Tarjan(int u)
{
dfn[u] = low[u] = ++ timer;
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
if(v == fa[u]) continue;
if(!dfn[v])
{
fa[v] = u; Tarjan(v);
low[u] = min(low[u], low[v]);
}
else low[u] = min(low[u], dfn[v]);
if(low[v] > dfn[u]) E2.add(u, v, );
}
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
if(dfn[u] < dfn[v] && fa[v] != u) Solve(u, v);
}
} void update(int u, int w)
{
if(w <= f[u][]) return;
if(w < f[u][]) f[u][] = w;
else f[u][] = f[u][], f[u][] = w;
} bool cmp(int a, int b) { return id[a] < id[b]; } int Work(int u)
{
int head = , tail = , cnt = , ans = , len = ;
for(int i = E2.head[u]; i; i = E2.last[i])
tmp[++ cnt] = f[E2.to[i]][], len ++;
for(int i = ; i <= len; ++ i)
tmp[++ cnt] = tmp[i];
q[head] = ;
for(int i = ; i <= cnt; ++ i)
{
while(head < tail && i - q[head] > len / ) ++ head;
ans = max(ans, tmp[i] + tmp[q[head]] + i - q[head]);
while(head <= tail && tmp[i] - i > tmp[q[tail]] - q[tail] ) -- tail;
q[++ tail] = i;
}
return ans;
} void dfs(int u, int ff)
{
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i];
if(v == ff) continue; else dfs(v, u);
update(u, f[v][] + E2.w[i]);
}
if(u <= n) ans = max(ans, f[u][] + f[u][]);
else ans = max(ans, Work(u));
} int main()
{
N = n = read(), m = read();
for(int i = ; i <= m; i ++)
{
int tot = read(), u, pre;
for(int j = ; j <= tot; j ++)
{
u = read(); if(j == ) { pre = u; continue; }
E1.add(u, pre, ); pre = u;
}
}
Tarjan();
dfs(, );
printf("%d\n", ans);
return ;
}

【题解】SHOI2008仙人掌图的更多相关文章

  1. [SHOI2008]仙人掌图

    [SHOI2008]仙人掌图 LG传送门 还不会仙人掌的同学可以看看我对仙人掌知识的一些梳理. 题意就是求仙人掌的直径,直径定义为图中最短路径最长的两点间的最短路径长度. 按照套路,先考虑求树的直径我 ...

  2. 洛谷 P4244 [SHOI2008]仙人掌图 II 解题报告

    P4244 [SHOI2008]仙人掌图 II 题目背景 题目这个II是和SHOI2006的仙人掌图区分的,bzoj没有. 但是实际上还是和bzoj1023是一个题目的. 题目描述 如果某个无向连通图 ...

  3. BZOJ1023:[SHOI2008]仙人掌图——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1023 Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple ...

  4. SHOI2008仙人掌图(tarjan+dp)

    Solution 好题啊没的说. 本题需要求出仙人掌的直径,但仙人掌是一个带有简单环的一张图无法直接用树形dp求解,但它有一个好东西就是没有类似环套环的东西,所以我们在处理时就方便了一些. 思路:ta ...

  5. [SHOI2008]仙人掌图 II——树形dp与环形处理

    题意: 给定一个仙人掌,边权为1 距离定义为两个点之间的最短路径 直径定义为距离最远的两个点的距离 求仙人掌直径 题解: 类比树形dp求直径. f[i]表示i向下最多多长 处理链的话,直接dp即可. ...

  6. BZOJ1023 SHOI2008 仙人掌图 仙人掌、单调队列

    传送门 求仙人掌的直径,可以由求树的直径进行拓展,只需要在环上特殊判断. 沿用求树的直径的DP,对于一条不在任何环内的边,直接像树的直径一样转移,然后考虑环的影响. 设环长为\(cir\),在\(df ...

  7. Luogu 4244 [SHOI2008]仙人掌图

    BZOJ 1023 如果我们把所有的环都缩成一个点,那么整张图就变成了一棵树,我们可以直接$dp$算出树的直径. 设$f_x$表示$x$的子树中最长链的长度,那么对于$x$的每一个儿子$y$,先用$f ...

  8. P4244 [SHOI2008]仙人掌图 II

    传送门 仙人掌直径,以前好像模拟赛的时候做到过一道基环树的直径,打了个很麻烦的然而还错了--今天才发现那就是这个的弱化版啊-- 如果是树的话用普通的dp即可,记\(f[u]\)表示\(u\)往下最长能 ...

  9. 洛谷P4244 [SHOI2008]仙人掌图 II

    传送门 首先不考虑带环的仙人掌,如果只是一棵普通的树,可以通过dp求每棵子树中的最长链和次长链求树的直径. 那么如果dfs的时候遇到了环,应该用环上的两点挂着的最长链加上两点间的距离来更新树的直径,并 ...

随机推荐

  1. pycharm中每次创建py文件时就自动生成代码头,以及出现SyntaxError:Non-ASCII 。。。问题

    我们在pycharm中执行py文件的时候,可能会出现以下错误 这是因为你没有制定编码格式,这时候你需要在文件最开始制定编码格式,代码如下 #!/user/bin/env python #-*- cod ...

  2. MetInfo最新网站漏洞如何修复以及网站安全防护

    metinfo漏洞于2018年10月20号被爆出存在sql注入漏洞,可以直接拿到网站管理员的权限,网站漏洞影响范围较广,包括目前最新的metinfo版本都会受到该漏洞的攻击,该metinfo漏洞产生的 ...

  3. ffplay使用笔记

    ffplay播放yuv文件命令: ffplay -f rawvideo -video_size 1920x1080 a.yuv   ffplay播放mp4.h.264.hevc文件命令: ffplay ...

  4. xss挑战赛小记 0x03(xssgame)

    0x00 继续做xss吧 这次是xssgame 地址 http://www.xssgame.com/ 一共八关 学到了很多东西 0x01 啥也没有 <svg/onload="alert ...

  5. 2019js面试题前端必问点小视频

    其实市面上的面试题有很多,但是大部分都是总结的blog居多,有时候说明一个事物也许口述几分钟就可以搞定,但是看帖子可能要分析半天 所以我就出一部分前端js必考的小视频,不管我们什么时候面试基本都绕不过 ...

  6. Python 3基础教程24-读取csv文件

    本文来介绍用Python读取csv文件.什么是csv(Comma-Separated Values),也叫逗号分割值,如果你安装了excel,默认会用excel打开csv文件. 1. 我们先制作一个c ...

  7. zabbix 一些问题随记

    1. zabbix运行不了,显示被锁,去检查日志中的报错 2. 配置界面,连接不到数据库,检查server配置文件,mysql授权命令要准确,重启 3. 显示没有php文件,下载即可,或者修改网页访问 ...

  8. 用Python 的一些用法与 JS 进行类比,看有什么相似?

    Python 是一门运用很广泛的语言,自动化脚本.爬虫,甚至在深度学习领域也都有 Python 的身影.作为一名前端开发者,也了解 ES6 中的很多特性借鉴自 Python (比如默认参数.解构赋值. ...

  9. javascript中容易出bug的语句

    一.forEach方法 forEach方法中没法用continue来实现跳过单句到下一次循环,如果要跳到下一次循环,要用return关键字,如果想直接跳出forEach循环,具我所知的,要throw一 ...

  10. 【CodeForces】9B-Running Student

    目录 Question Description Input Output Solution 解法1 Question Description 小明在公交车始发站上车,他应该在哪个站点下车才能最快到达学 ...