这道题是我做的第一道仙人掌DP,小小纪念一下……

仙人掌DP就是环上的点环状DP,树上的点树上DP。就是说,做一遍DFS,DFS的过程中处理出环,环上的点先不DP,先把这些换上的点的后继点都处理出来,再从环上DFS序最小的点开始进行环状DP,就ok了。但是注意判断是不是父边不能用 v[k] != fa[now],这样如果两个点构成一个环就会出错,所以存这个点的父边,记为fb[now],这样判断的时候只需判断(k^1) != fb[now],就可以了。在环状DP的时候我想了很久怎么用单调队列优化(其实是我太弱了,环状DP都不会写=_=)。存一个p[i] = f[i]-i,然后用 f[i]+i+p[j] 更新答案就可以了,最后只需更新环最顶端的点的 f 值而不用全部修改。

这么说很笼统,还是看代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#define N 500100
#define M 1001000
using namespace std; int n, m;
int p[N], next[M], v[M], bnum = -;
int f[N] = {};
int ans = ; void addbian(int x, int y)
{
bnum++; next[bnum] = p[x]; p[x] = bnum; v[bnum] = y;
bnum++; next[bnum] = p[y]; p[y] = bnum; v[bnum] = x;
} int nowtime = ;
int low[N], vist[N] = {}, fb[N], fa[N];
bool instack[N] = {}; int roop[N], roopnum; struct ss
{
int place, val;
}dui[N];
int head, tail; void work_circle()
{
int limit = roopnum/;
for (int i = roopnum+; i <= (roopnum<<); ++i) roop[i] = roop[i-roopnum];
ss x; x.val = f[roop[]]-; x.place = ;
head = ; tail = ; dui[head] = x;
for (int i = ; i <= (roopnum<<); ++i)
{
while (dui[head].place+limit < i) head++;
ans = max(ans, f[roop[i]]+i+dui[head].val);
x.val = f[roop[i]]-i; x.place = i;
while (dui[tail].val < x.val && tail >= head) tail--;
dui[++tail] = x;
}
} void dfs(int now)
{
int k = p[now]; vist[now] = ++nowtime; low[now] = vist[now];
while (k != -)
{
if (k != fb[now])
{
if (vist[v[k]]) low[now] = min(low[now], vist[v[k]]);
else
{
fa[v[k]] = now; fb[v[k]] = k^;
dfs(v[k]);
low[now] = min(low[now], low[v[k]]);
}
}
k = next[k];
}
k = p[now];
while (k != -)
{
if ((k^) == fb[v[k]] && low[v[k]] > vist[now])
{
ans = max(ans, f[now] + f[v[k]] + );
f[now] = max(f[now], f[v[k]] + );
}
if ((k^) != fb[v[k]] && vist[now] < vist[v[k]])
{
roopnum = ;
int x = v[k];
while (x != fa[now])
{
roop[++roopnum] = x;
x = fa[x];
}
work_circle();
for (int i = ; i < roopnum; ++i)
f[now] = max(f[now], f[roop[i]]+min(i, roopnum-i));
}
k = next[k];
}
} int main()
{
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i) p[i] = -;
for (int i = ; i <= m; ++i)
{
int k, x, y; scanf("%d%d", &k, &x);
for (int j = ; j < k; ++j)
{
scanf("%d", &y);
addbian(x, y);
x = y;
}
}
fa[] = ; fb[] = -; dfs();
printf("%d\n", ans);
return ;
}

bzoj 1023: [SHOI2008]cactus仙人掌图的更多相关文章

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

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

  2. 【刷题】BZOJ 1023 [SHOI2008]cactus仙人掌图

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

  3. BZOJ 1023: [SHOI2008]cactus仙人掌图 | 在仙人掌上跑DP

    题目: 求仙人掌直径 http://www.lydsy.com/JudgeOnline/problem.php?id=1023 题解: 首先给出仙人掌的定义:满足所有的边至多在一个环上的无向联通图 我 ...

  4. bzoj 1023: [SHOI2008]cactus仙人掌图 2125: 最短路 4728: 挪威的森林 静态仙人掌上路径长度的维护系列

    %%% http://immortalco.blog.uoj.ac/blog/1955 一个通用的写法是建树,对每个环建一个新点,去掉环上的边,原先环上每个点到新点连边,边权为点到环根的最短/长路长度 ...

  5. bzoj 1023 [SHOI2008]cactus仙人掌图 ( poj 3567 Cactus Reloaded )——仙人掌直径模板

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1023 http://poj.org/problem?id=3567 因为lyd在讲课,所以有 ...

  6. BZOJ.1023.[SHOI2008]cactus仙人掌图(DP)

    题目链接 类似求树的直径,可以用(类似)树形DP求每个点其子树(在仙人掌上就是诱导子图)最长链.次长链,用每个点子节点不同子树的 max{最长链}+max{次长链} 更新答案.(不需要存次长链,求解过 ...

  7. bzoj 1023: [SHOI2008]cactus仙人掌图【tarjan+dp+单调队列】

    本来想先求出点双再一个一个处理结果写了很长发现太麻烦 设f[u]为u点向下的最长链 就是再tarjan的过程中,先照常处理,用最长儿子链和次长儿子链更新按ans,然后处理以这个点为根的环,也就是这个点 ...

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

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

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

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

随机推荐

  1. gcc中不同namespace中同名class冲突时

    正常情况下,编译器都会报错,提示你有两个候选类,让你明确的选择一个. 比如我的情况,我自己设计了一个类Message, 然后在某个文件里面引用了它.但是我的文件中又引入了mongodb的头文件,非常不 ...

  2. [Angular 2] Create Shareable Angular 2 Components

    Components that you use across multiple applications need to follow a module pattern that keeps them ...

  3. C语言连接MySQL数据库(课程设计总结)

    刚结束课程设计,也预示着假期立即就要到来了.本次课程设计并不算难,无非就是让做一个XXX系统,实现用户的注冊.登录.菜单管理.超级用户等等一些功能,到如今为止已经做过好几个了,所以基本流程都熟悉了! ...

  4. 关于dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的分发机制浅析

    虽说这个问题不是很难...动动手就能看出答案...但是似乎不太容易理解...几次尝试把这个问题说明白....但是好像感觉说不明白....(顿时想起了那句话----说不明白就是自己还不明白! 我怎么可能 ...

  5. 解决Download interrupted: Connection to https://dl-ssl.google.com refused的问题

    运行->drivers->etc->hosts 加入一行 74.125.237.1 dl-ssl.google.com ok! =================上述方法已经失效, ...

  6. IIS 之 添加绑定域名 或 设置输入IP直接访问网站

    1.打开IIS,右键站点 → 编辑绑定,弹出“网站绑定”窗口,如下图:   2.点击“添加”,弹出“添加网站绑定”窗口,如下图:   注意:若想输入 IP 地址直接访问,则可以有以下两种设置任一均可: ...

  7. Scheme中一些函数在C++里面的实现与吐槽

          最终我失败了,这是显而意见,我试图在一个很看重类型是什么的语言中实现无类型操作,事实上,哪怕我实现了基本的cons,car,cdr,list后面的代码也无法写下去.比如说list-n,根据 ...

  8. oracle11g asm standalone 单实例重建

    原文地址:oracle11g asm单实例重建has 作者:datapeng 最近到客户那里处理故障,客户说,他们修改了一下hostname,导到has出现了问题,当然,他们的数据库也就无法再启动,把 ...

  9. SQLServer-镜像配置

    实验环境:三台服务器分别为主服务器,镜像服务器,见证服务器,都加入域sql.com 1. 分别在三台服务器上安装SQL 2008 R2,安装数据库引擎和管理工具两个组件即可. 2. 镜像前准备工作. ...

  10. LeetCode 122

    Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price of a ...