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

举例来说,上面的第一个例子是一张仙人图,而第二个不是——注意到它有三条简单回路:(4,3,2,1,6,5,4)、(7,8,9,10,2,3,7)以及(4,3,7,8,9,10,2,1,6,5,4),而(2,3)同时出现在前两个的简单回路里。另外,第三张图也不是仙人图,因为它并不是连通图。显然,仙人图上的每条边,或者是这张仙人图的桥(bridge),或者在且仅在一个简单回路里,两者必居其一。定义在图上两点之间的距离为这两点之间最短路径的距离。定义一个图的直径为这张图相距最远的两个点的距离。现在我们假定仙人图的每条边的权值都是1,你的任务是求出给定的仙人图的直径。
Input
输入的第一行包括两个整数n和m。其中n代表顶点个数,我们约定图中的顶点将从1到n编号。接下来一共有m行。代表m条路径。每行的开始有一个整数k,代表在这条路径上的顶点个数。接下来是k个1到n之间的整数,分别对应了一个顶点,相邻的顶点表示存在一条连接这两个顶点的边。一条路径上可能通过一个顶点好几次,比如对于第一个样例,第一条路径从3经过8,又从8返回到了3。
Output
只需输出一个数,这个数表示仙人图的直径长度。
Sample Input
15 3
9 1 2 3 4 5 6 7 8 3
7 2 9 10 11 12 13 10
5 2 14 9 15 10
Sample Output
8
HINT
1≤n≤50000,0≤m≤10000,2≤k≤1000。
保证所有的边都会出现在某条路径上,而且不会重复出现在两条路径上,或者在一条路径上出现两次。
如图,6号点和12号点的最短路径长度为8,所以这张图的直径为8。

Solution
关于业界毒瘤仙人掌的初探。
毕竟仙人掌的原型还是树,所以我们想办法把仙人掌转化成树来做。
最直接的想法是缩环,变成树形DP,然后自己在环内瞎搞搞来更新答案。
事实证明,这种方法是可行的。例如样例,我们可以通过缩点的方式把仙人掌转化成如下的树:

这样树上的每一个点都是一个环,环与环之间根据原图的构造连上0或1的边,这是最简单最无脑的建图方式。
现在我们考虑怎么在环内瞎搞:

假设一个这样的环,其中环上一些节点有通向儿子的边,红色节点上有通向父亲的边。
考虑最普通的树上DP求直径,我们很自然地对于每个环维护所有后辈中,距离红色节点最远的点的距离,以便向上更新答案。
这样我们就知道了这个环上所有拥有通向儿子的边的节点离它的所有后辈的最远距离,这样直接加上在环上离红色节点的距离就可以更新DP值。
当然,这个环上没有拥有通向儿子的边的节点也可以更新DP值,注意一下即可。
但是按照树形DP求直径,以该点为lca的直径是最大的两个儿子的DP值之和。如果放在一个环上该怎么求呢?
这个做法同样很经典,对于环,我们一般的做法是拆环成链,再把链复制一份接到后面来做,例如旋转卡壳的做法。
所以对于这个问题,我们同样只要把被拆环之后的链扫一遍,用单调队列维护每个点之前的最大值来更新就好了。
这也大概就是最笨的算法的整个流程。
缩环建图虽然简单,但写起来确实复杂。但基于以上思想,我们依然可以对代码进行优化。
在缩环建图的时候,我们实际上已经找出了仙人掌图的dfs树,然后对于每条返祖边,我们建立一个环。
这条返祖边是名副其实的返祖边,一定会返回到该点的祖先。也就是说,图中的环一定对应的是dfs树上一条由上到下的链。

而且根据仙人掌图的性质,这些链不会相交。
再仔细想想,这些链中深度最小的点,不就是我们刚刚所说的环内的红色节点么?
所以我们在对一个环进行DP的时候,只要把得到的信息丢到环中深度最小的点里就可以了。
然后对于非环边x→y(也就是图中的桥),直接更新f[x]=max(f[x],f[y]+1)即可。
还有就是处理顺序的问题。例如样例,我们在遍历到10号节点后,必须先往11号节点走而不是15号节点。
因为在15号节点对于9号节点的更新有赖于13号节点对10号节点的更新。
剩下就是代码实现的问题了。这样的代码会比之前介绍的的方法简洁很多。
时间复杂度O(n+mk)。第一种方法写得太丑就不发了。
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MN 100005
#define MM 5000005
using namespace std;
struct edge{int nex,to;}e[MM];
bool u[MN],ih[MN];
int hr[MN],dep[MN],lto[MN],dw[MN],bac[MN],f[MN],sk[MN],q[MN];
int pin,tp,hd,tl,ans,n,m,p,pre; inline int read()
{
int n=,f=; char c=getchar();
while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
while (c>='' && c<='') {n=n*+c-''; c=getchar();}
return n*f;
} inline void ins(int x,int y) {e[++pin]=(edge){hr[x],y}; hr[x]=pin;}
inline int dis(int x,int y) {return x<=y/?x:y-x;} void dp(int x,int depth)
{
register int i;
u[x]=true; dw[depth]=x;
for (i=hr[x];i;i=e[i].nex)
{
if (u[e[i].to]||e[i].to==lto[x]) continue;
dp(e[i].to,depth+);
if (!ih[e[i].to]) ans=max(ans,f[x]+f[e[i].to]+),f[x]=max(f[x],f[e[i].to]+);
}
if (lto[x]) dp(lto[x],depth+);
if (bac[x])
{
tp=;
for (i=dep[bac[x]];i<=dep[x];++i) sk[tp++]=f[dw[i]];
for (i=;i<tp;++i) sk[tp+i]=sk[i];
tp<<=; hd=; tl=;
for (i=;i<tp;++i)
{
if (i<(tp>>)) f[bac[x]]=max(f[bac[x]],sk[i]+dis(i,tp>>));
for (;hd<=tl&&i-q[hd]>(tp>>);++hd);
if (hd<=tl) ans=max(ans,sk[i]+sk[q[hd]]+i-q[hd]);
for (;hd<=tl&&sk[i]-i>=sk[q[tl]]-q[tl];--tl);
q[++tl]=i;
}
}
ans=max(ans,f[x]);
} void dfs(int x,int fat,int depth)
{
register int i,j;
u[x]=true; dep[x]=depth; dw[depth]=x;
for (i=hr[x];i;i=e[i].nex)
{
if ((i^)==fat) continue;
if (u[e[i].to])
{
for (j=dep[e[i].to]+;j<dep[x];++j) lto[dw[j]]=dw[j+];
for (j=dep[e[i].to]+;j<=dep[x];++j) ih[dw[j]]=true;
if (dep[x]>dep[e[i].to]) bac[x]=e[i].to;
}
else dfs(e[i].to,i,depth+);
}
} int main()
{
register int x,i;
n=read(); m=read(); pin=;
while (m--)
for (p=read()-,pre=read();p;--p)
x=read(),ins(x,pre),ins(pre,x),pre=x;
memset(u,,sizeof(u)); dfs(,,);
memset(u,,sizeof(u)); dp(,);
printf("%d\n",ans);
}
Last Word
顺带一提,基环外向树也是通过把环取出来转化成树上问题的,而基环外向树也是一种特殊的仙人掌。
基环外向树在BZOJ第一页同样有一道裸题:BZOJ1040。
所以仙人掌什么的大概就是这种模型了吗?
[BZOJ]1023 cactus仙人掌图(SHOI2008)的更多相关文章
- 【BZOJ】【1023】【SHOI2008】cactus仙人掌图
DP+单调队列/仙人掌 题解:http://hzwer.com/4645.html->http://z55250825.blog.163.com/blog/static/150230809201 ...
- bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列
1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1141 Solved: 435[Submit][ ...
- bzoj千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图
http://www.lydsy.com/JudgeOnline/problem.php?id=1023 dp[x] 表示以x为端点的最长链 子节点与x不在同一个环上,那就是两条最长半链长度 子节点与 ...
- SHOI2008 cactus仙人掌图 和 UOJ87 mx的仙人掌
cactus仙人掌图 题目描述 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一 ...
- 1023: [SHOI2008]cactus仙人掌图 - BZOJ
Description如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路 ...
- 【刷题】BZOJ 1023 [SHOI2008]cactus仙人掌图
Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的 ...
- 【BZOJ】1023: [SHOI2008]cactus仙人掌图 静态仙人掌(DFS树)
[题意]给定仙人掌图(每条边至多在一个简单环上),求直径(最长的点对最短路径).n<=50000,m<=10^7. [算法]DFS树处理仙人掌 [题解]参考:仙人掌相关问题的处理方法(未完 ...
- bzoj 1023: [SHOI2008]cactus仙人掌图 2125: 最短路 4728: 挪威的森林 静态仙人掌上路径长度的维护系列
%%% http://immortalco.blog.uoj.ac/blog/1955 一个通用的写法是建树,对每个环建一个新点,去掉环上的边,原先环上每个点到新点连边,边权为点到环根的最短/长路长度 ...
- 1023: [SHOI2008]cactus仙人掌图(DP+单调队列优化)
这道题吗= =首先解决了我多年以来对仙人掌图的疑问,原来这种高大上的东西原来是这个啊= = 然后,看到这种题,首先必须的就是缩点= = 缩点完之后呢,变成在树上找最长路了= =直接树形dp了 那么那些 ...
随机推荐
- python3变量和数据类型
变量和数据类型 知识点 python 关键字 变量的定义与赋值 input() 函数 字符串的格式化 实验步骤 每一种编程语言都有它们自己的语法规则,就像我们所说的外语. 1. 关键字和标识符 ...
- HTTP协议中PUT和POST使用区别
有的观点认为,应该用POST来创建一个资源,用PUT来更新一个资源:有的观点认为,应该用PUT来创建一个资源,用POST来更新一个资源:还有的观点认为可以用PUT和POST中任何一个来做创 ...
- bzoj千题计划243:bzoj2325: [ZJOI2011]道馆之战
http://www.lydsy.com/JudgeOnline/problem.php?id=2325 设线段树节点区间为[l,r] 每个节点维护sum[0/1][0/1] 从l的A/B区域到r的 ...
- NOIP2012 提高组 Day 2
http://www.cogs.pro/cogs/page/page.php?aid=16 期望得分:100+100+0=0 实际得分:100+20+0=120 T2线段树标记下传出错 T1 同余方程 ...
- win10 安装mingw ruby rails
原文可以参考 https://ruby-china.org/topics/17581 在window10 安装ruby rails https://rubyinstaller.org/download ...
- python 3.x 爬虫基础---常用第三方库(requests,BeautifulSoup4,selenium,lxml )
python 3.x 爬虫基础 python 3.x 爬虫基础---http headers详解 python 3.x 爬虫基础---Urllib详解 python 3.x 爬虫基础---常用第三方库 ...
- MobileNet_v2
研究动机: 神经网络彻底改变了机器智能的许多领域,实现了超人的准确性.然而,提高准确性的驱动力往往需要付出代价:现代先进网络需要高度计算资源,超出许多移动和嵌入式应用的能力. 主要贡献: 发明了一个新 ...
- 解决vue2.0路由 TypeError: Cannot read property 'matched' of undefined 的错误问题
刚开始使用vue-router2.0,虽然也用了vux,用起来却发现一个问题--具体如下: 正常情况下使用脚手架跑完之后,然后修改源项目,首先在main.js入口里把该import进去的vuex,vu ...
- STM32读取温湿度传感器DHT11和DHT21(AM2301)系列问题
1.DHT11和DHT21传感器 这两种传感器都是奥松公司的产品,具体的传感器说明书在其官网上有(www.aosong.com). DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合 ...
- Mybatis的mapper代理开发dao方法
看完了之前的mybatis原始的dao开发方法是不是觉得有点笨重,甚至说没有发挥mybatis 作为一个框架的优势.总结了一下,原始的dao方法有以下几点不足之处 dao接口实现方法中存在大量的模板方 ...