【题意】给定仙人掌图(每条边至多在一个简单环上),求直径(最长的点对最短路径)。n<=50000,m<=10^7。

【算法】DFS树处理仙人掌

【题解】参考:仙人掌相关问题的处理方法(未完待续)

对仙人掌建立DFS树,参考无向图的点双连通分量Tarjan算法,在访问x时容易知道边(x,y)是否属于一个环。

设f[x]表示x点向下延伸的最长链长度,对于不在环上的边(x,y),有f[x]=max{f[y]+1}。统计直径可以在访问每个y时进行ans=max{ans,f[x]+f[y]+1}从而完成子树x对答案的贡献。

对于一个环,只在其DFS树中深度最小的点进行处理(其它点直接忽略环边的存在),假设当前这个点为x,其与深度最大的点y的连边为(x,y)。(这条边只要满足fa[y]≠x&&dfn[y]>dfn[x]就可以找到)

假设这个环有cnt个点,在环上只有距离<=cnt/2的点对可以贡献答案。我们只需要维护每个点和其前面半圈的点构成的点对中的最大值,这可以用单调队列维护。

但这样的话,前半圈的点与前面的点对会少考虑一部分,所以将环延伸半圈,即维护一圈半的点。最后记得枚举整个环更新f[x]。

复杂度O(m)。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
int read(){
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
const int maxn=,maxm=;
struct edge{int v,from;}e[maxm];
int first[maxn],tot,fa[maxn],a[maxn],f[maxn],q[maxn],dfn[maxn],low[maxn],ans,dfsnum=,n,m;
void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
void solve(int A,int B){
int cnt=;
for(int i=B;i!=A;i=fa[i])a[++cnt]=f[i];a[++cnt]=f[A];
for(int i=;i<=cnt/;i++)swap(a[i],a[cnt-i+]);
for(int i=cnt+;i<=cnt+(cnt>>);i++)a[i]=a[i-cnt];
int head=,tail=;q[head]=;
for(int i=;i<=cnt+(cnt>>);i++){
if(head<tail&&i-q[head]>cnt/)head++;
ans=max(ans,a[i]+a[q[head]]+i-q[head]);
while(head<tail&&a[i]-i>=a[q[tail-]]-q[tail-])tail--;
q[tail++]=i;
}
for(int i=;i<=cnt;i++)f[A]=max(f[A],a[i]+min(i-,cnt-i+));
}
void dfs(int x,int father){
dfn[x]=low[x]=++dfsnum;f[x]=;
for(int i=first[x];i;i=e[i].from)if(e[i].v!=father){
int y=e[i].v;
if(!dfn[y]){
fa[y]=x;
dfs(y,x);
low[x]=min(low[x],low[y]);
}else low[x]=min(low[x],dfn[y]);
if(low[y]>dfn[x]){
ans=max(ans,f[x]+f[y]+);
f[x]=max(f[x],f[y]+);
}
}
for(int i=first[x];i;i=e[i].from)
if(e[i].v!=father&&fa[e[i].v]!=x&&dfn[e[i].v]>dfn[x])solve(x,e[i].v);
}
int main(){
n=read();m=read();
for(int i=;i<=m;i++){
int k=read(),u=read();
for(int j=;j<=k;j++){
int v=read();
insert(u,v);insert(v,u);
u=v;
}
}
ans=;
dfs(,);
printf("%d",ans);
return ;
}

【BZOJ】1023: [SHOI2008]cactus仙人掌图 静态仙人掌(DFS树)的更多相关文章

  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仙人掌图 2125: 最短路 4728: 挪威的森林 静态仙人掌上路径长度的维护系列

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

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

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

  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就是环上的点环状DP,树上的点树上DP.就是说,做一遍DFS,DFS的过程中处理出环,环上的点先不DP,先把这些换上的点的后继点都处理出来, ...

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

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

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

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

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

    [BZOJ1023]仙人掌图(仙人掌,动态规划) 题面 BZOJ 求仙人掌的直径(两点之间最短路径最大值) 题解 一开始看错题了,以为是求仙人掌中的最长路径... 后来发现看错题了一下就改过来了.. ...

随机推荐

  1. 第5章 Linux 常用网络指令

    网络参数设定使用的指令 手动/自动设定与启动/关闭 IP 参数: ifconfig, ifup, ifdown ifconfig :查询.设定网络卡与 IP 网域等相关参数:ifup, ifdown: ...

  2. erlang中检查内存泄露

    最近项目内存占用过多,检查一下erlang的内存使用情况. 1. 通过etop可以很方便得出erlang内存使用的情况 spawn(fun() -> etop:start([{output, t ...

  3. so加载报错:dlopen failed: couldn't map ... Permission denied

    转自:https://blog.csdn.net/u013270444/article/details/60869376 问题描述: 我的应用当中集成了一个安全相关的sdk,而这个sdk中使用的so是 ...

  4. phpcms前端模板目录与文件结构分析图【templates】

    phpcms前端模板目录与文件结构分析图[templates] 原文地址:http://www.iphpcms.net/phpcms-ziliao/2015_14.html

  5. C#和Java在多态情况下对成员访问的比较

    本文简单比较一下两种语言在里氏替换原则下,父类引用变量访问成员时的访问结果: 如果有两个类,如Person与Student,后者继承了前者,而且子类与父类有重名成员,当Person p = new S ...

  6. SPOJ PGCD

    今天做的一个很有成就感的题目,虽然经过我一个上午的痛苦挣扎,但是我觉得这个时间还是花的挺有意义的. 题目的意思是给你a和b两个数(范围是10^7),从1-a选一个数x,从1-b中间选择一个数,问你能选 ...

  7. floyd最短路

    floyd可以在O(n^3)的时间复杂度,O(n^2)的空间复杂度下求解正权图中任意两点间的最短路长度. 本质是动态规划. 定义f[k][i][j]表示从i出发,途中只允许经过编号小于等于k的点时的最 ...

  8. bzoj4770 图样

    题意 n个点的完全图,每个点的点权是在m位的二进制数中随机选取的.每条边的边权是两个点的点权的异或值. 问最小生成树的边权和的期望.模一个质数输出. 分析 考试的时候写这个题,然后期望得分100-&g ...

  9. (转)linux下压缩和归档相关命令tar,zip,gzip,bzip2

    压缩包也有两种形式,一种是tar.gz包(.tgz包也是这种),一种是tar.bz2包. tar.gz包的解压方法:tar zxvf [PackageName].tar.gz tar.bz2包的解压方 ...

  10. String和stringbuffer和stringbuilder的区别

    String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主要 ...