【BZOJ1023】仙人掌图(仙人掌,动态规划)

题面

BZOJ

求仙人掌的直径(两点之间最短路径最大值)

题解

一开始看错题了,以为是求仙人掌中的最长路径。。。

后来发现看错题了一下就改过来了。。

首先和普通的仙人掌\(dp\)是一样的,

对于没有问题的圆圆边,直接做最长链的转移(同时更新\(ans\))

然后对于一个环,把它拎出来单独考虑

首先要对于这个环,计算能够贡献的答案,

然后再用环上的值更新环的最顶点

先考虑怎么更新,这个直接拿环上的点的\(dp\)值,再计算一下这两点之间的最短路(深度差和环大小减深度差的较小值),相加去更新\(dp\)值。

然后考虑一下如何贡献答案,

要求的相当于是\(max(f[i]+f[j]+dist(i,j))\)

而\(dist(i,j)=min(abs(dep[i]-dep[j]),circle\_size-abs(dep[i]-dep[j]))\)

发现维护一个单调队列,按照深度依次进栈,

这样子距离直接可以用深度做差,没有了绝对值

因为可以通过返祖边回去,因此把所有点按照顺序进两次队就可以了

第二次进队的时候给深度加上一个环大小再进队

然后如何保证是环上的最短路?

如果两个深度差已经大于环大小的一半了,那么最短路就不是这一条了

所以直接弹走队首就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 55555
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Line{int v,next;}e[MAX<<3];
int h[MAX],cnt=1,n,m;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int f[MAX],ans=1,fa[MAX],dep[MAX],dfn[MAX],low[MAX],tim;
int H,T,Q1[MAX<<1],Q[MAX<<1];
void dp(int u,int y)
{
int t=0;
for(int i=y;i!=u;i=fa[i])Q1[++t]=i;Q1[++t]=u;
reverse(&Q1[1],&Q1[t+1]);
for(int i=1;i<=t;++i)Q1[i+t]=Q1[i];
H=1;T=0;
for(int i=1;i<=t+t;++i)
{
while(H<=T&&i-Q[H]>t/2)++H;
if(H<=T)ans=max(ans,f[Q1[i]]+f[Q1[Q[H]]]+i-Q[H]);
while(H<=T&&f[Q1[i]]-i>f[Q1[Q[T]]]-Q[T])--T;
Q[++T]=i;
}
for(int i=y;i!=u;i=fa[i])
f[u]=max(f[u],f[i]+min(dep[i]-dep[u],1+dep[y]-dep[i]));
}
void dfs(int u,int ff)
{
fa[u]=ff;dfn[u]=low[u]=++tim;dep[u]=dep[ff]+1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(!dfn[v])dfs(v,u),low[u]=min(low[u],low[v]);
else if(v!=ff)low[u]=min(low[u],dfn[v]);
if(low[v]>dfn[u])
ans=max(ans,f[u]+f[v]+1),f[u]=max(f[u],f[v]+1);
}
for(int i=h[u];i;i=e[i].next)
if(fa[e[i].v]!=u&&dfn[u]<dfn[e[i].v])
dp(u,e[i].v);
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;++i)
{
int K=read(),a=read();
for(int j=1;j<K;++j)
{
int b=read();
Add(a,b);Add(b,a);
a=b;
}
}
dfs(1,0);
printf("%d\n",ans);
return 0;
}

【BZOJ1023】仙人掌图(仙人掌,动态规划)的更多相关文章

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

    Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3467  Solved: 1438[Submit][Status][Discuss] Descripti ...

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

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

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

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

  4. 【bzoj1023】仙人掌图

    [bzoj1023]仙人掌图 题意 给一棵仙人掌,求直径. \(n\leq 100000\) 分析 分析1:[Tarjan]+[环处理+单调队列优化线性dp]+[树形dp] 分开两种情况处理: ①环: ...

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

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

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

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

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

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

  8. BZOJ1023[SHOI2008]cactus仙人掌图 【仙人掌DP】

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

  9. 仙人掌图判定及求直径HDU3594 BZOJ1023

    https://wenku.baidu.com/view/ce296043192e45361066f575.html   //仙人掌图基础知识3个判定条件 http://blog.csdn.net/y ...

随机推荐

  1. Python_函数的初识、函数的返回值、函数的参数

    1.函数的初识 def关键字 空格 函数名(与变量名命名规则相同):英文冒号 函数体 执行函数:函数名+() 函数是以功能为导向的. def login(): pass def register(): ...

  2. Git使用过程中的问题

    Q-1:怎么切换到远程的分支 本地已经有一个代码库了(是从github上clone的),但是现在远程库中一个新的branch,怎么拉取远程分支,并在本地创建该分支(内容一样).how to do? # ...

  3. 安装sqlprompt

    特别说明:注册机会报毒,安装前请先关闭杀毒软件!下载好附件之后解压,打开SQLPrompt_7.2.0.241.exe按照提示安装完成.安装完成后断网!打开数据库,会在菜单栏中看到SQL Prompt ...

  4. 谈谈git/github

    先说git/github操作 ->关于git/github操作的好文章已经非常多,如: github使用指南 廖雪峰的git教程 本文的目的在于,积累自己平时相关的操作和想法,记录下来,形成自己 ...

  5. 爬取B站视频

    先安装you_get pip install you_get 爬取代码,爬了个ASMR的,学习困了自我催眠 import sys from you_get import common as you_g ...

  6. 【gedit】 显示行号

    打开gedit文本编辑器->Edit(编辑)->preferences(预设)->view(视图)->在Display line numbers前打勾->close

  7. django migrate报错(提前删除表等)

    python3 manage.py makemigrations python3 manage.py migrate ##报错 改为##更改migrates的状态 python3 manage.py ...

  8. varnish4 配置文件整理

    vim default.vcl # 使用varnish版本4的格式. vcl 4.0; # 加载后端轮询模块 import directors; #######################健康检查 ...

  9. 用python写一个预警机器人(支持微信和钉钉)

    背景 线上的系统在运行中,发生故障时怎么及时的通过手机通知到相关人员?当然这是个很简单的需求,现有的方法有很多,例如: 如果我们用的云产品,那么一般都会有配套对应的监控预警功能,根据需要配置一下即可, ...

  10. The Bug and Exception of Hibernate

    1: hibernate4.3.5 的@oneToOne注解有Bug,建议不使用该版本,或者使用该版本不使用@table   annotation. 2:今天在用hibernate4.2.13的时候, ...