【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.创建进程 守护进程(*****) _.daemon = True #  _进程成为守护进程 守护进程也是一个子进程. 主进程的<代码>执行结束之后守护进程自动结束. import ti ...

  2. CRM系统设计方案

    CRM系统设计方案 - 百度文库https://wenku.baidu.com/view/a34eebeb0242a8956bece473.html 服务支持http://www.uf-crm.com ...

  3. opencv2\core\cuda.hpp(106): error C2059: 语法错误:“常量”

    在 cuda.hpp 中, virtual void free(GpuMat* mat) = 0;   -> virtual void _free(GpuMat* mat) = 0;

  4. 【学亮IT手记】Ajax跨域问题精讲--jQuery解决跨域操作

    什么是跨域 跨域,它是不同的域名(服务器)之间的相互的资源之间的访问. 当协议,域名,端口号任意一个不同,它们就是不同的域. 正常情况下,因为浏览器安全的问题,不同域之间的资源是不可以访问的. 跨域的 ...

  5. C++多态(静多态和动多态)

    如今的C++已经是个多重泛型编程语言(multiparadigm programming lauguage),一个同时支持过程形式(procedural).面向对象形式(object-oriented ...

  6. docker遇到的问题以及docker 操作镜像的基本操作

    root@localhost ~]# systemctl status docker.service ● docker.service - Docker Application Container E ...

  7. 1、通过eureka创建注册中心

    第一个demo(用户需要调用电影服务) 1.创建项目 new starter project 勾选上Eureka Server 2.编写application.yml #配置端口 server: po ...

  8. git(命令行常用炒作)

    Git常用操作 https://backlog.com/git-tutorial/cn/intro/intro1_1.html Git详解(思维导图) https://blog.csdn.net/hu ...

  9. 多IP地址--笔记

    多IP 地址特性使虚拟用户可以在一个load generator上运行且被识别为多个IP地址 1 虚拟IP是同一个generator上的多个IP,这种分配过程由controller自动来进行 2 对于 ...

  10. Git要点

    前面的话 本文将总结Git要点 版本管理工具 [作用] 1.备份文件 2.记录历史 3.回到过去 4.对比差异 [分类] 1.手动版本控制(又叫人肉VCS) 2.LVCS 本地 3.CVCS 集中式( ...