bzoj1023【SHOI2008】cactus仙人掌图
题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1023
求一棵仙人掌的直径
sol :orz YDC神犇 http://ydcydcy1.blog.163.com/blog/static/21608904020131493113160/
orz z55250825神犇 http://z55250825.blog.163.com/blog/static/150230809201412793151890/
对于一棵仙人掌,只有两种边:环上的边以及割边(桥),这两种边需要分开讨论
先进行一遍dfs,得到一棵dfs树,然后考虑树形dp
定义f[i]表示在dfs树上,以i为根的子树且在i的诱导子图中以i为起点的最长链
P.S.诱导子图定义:G'=(V', E'),V'⊆V,E'={ (u, v) | u, v∈V',(u, v)∈E },则G'为G的诱导子图。
先考虑没有环的情况,对于最远点对所在的路径,一定有以下性质:
该路径必定存在一个节点,它在这条路径上的所有点中深度最小(这个易证)
所以,f[u]的转移方程为,f[u]=max(f[v]+1),答案即为最长的儿子+次长的儿子+2
考虑非树边,显然一条非树边会形成一个环,对于环上各点,其实是地位平等的,所以可以将环上信息放在最高点上并向上传递即可
考虑环会带来什么影响
对于点u及其儿子v,如果二者在同一个环上,且u不是最高点,则不用更新答案,直接跳过,搜索其他点
这是因为除最高点以外的点的f值只会影响到环上点的f值,而不会影响其他环的f值
跳过后可以看出,节点u的f值只储存了与不在同一个环上的点的最长路径,然后对环上的点进行更新
环上的点更新的原理我不是太明白,所以直接拷贝dalao的博客了QAQ

所以最后就是,对于环上的点u,v,用dis(u,v)+f[v]来更新f[u]即可
可以用单调队列维护,由于是环,将链长翻倍即可
如果是最高点的话,直接枚举一边计算即可
所以算法的流程就是,先tarjan判环,然后如果是桥就直接更新,否则把所有点取出然后dp这个环即可
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int Mx1=;
const int Mx2=;
int n,m,l,r,cnt,ans,dep[Mx1],f[Mx1],fa[Mx1],dfn[Mx1],low[Mx1];
int tot,head[Mx1],nxt[Mx2],ver[Mx2],a[*Mx1],q[*Mx1];
inline void add(int x,int y)
{
nxt[++tot]=head[x];
ver[tot]=y;
head[x]=tot;
}
void Dp(int root,int x)
{
tot=dep[x]-dep[root]+;
for(int i=x;i!=root;i=fa[i]) a[tot--]=f[i];
a[tot]=f[root];
tot=dep[x]-dep[root]+;
for(int i=;i<=tot;i++) a[i+tot]=a[i];
q[]=l=r=;
for(int i=;i<=*tot;i++)
{
while(l<=r&&i-q[l]>tot/) l++;
ans=max(ans,a[i]+i+a[q[l]]-q[l]);
while(l<=r&&a[q[r]]-q[r]<=a[i]-i) r--;
q[++r]=i;
}
for(int i=;i<=tot;i++)
f[root]=max(f[root],a[i]+min(i-,tot-i+));
} void Dfs(int x)
{
low[x]=dfn[x]=++cnt;
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i];
if(y!=fa[x])
{
if(!dfn[y])
{
fa[y]=x,dep[y]=dep[x]+;
Dfs(y);
low[x]=min(low[x],low[y]);
}
else low[x]=min(low[x],dfn[y]);
if(dfn[x]<low[y])
{
ans=max(ans,f[x]+f[y]+);
f[x]=max(f[x],f[y]+);
}
}
}
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i];
if(fa[y]!=x&&dfn[x]<dfn[y]) Dp(x,y);
}
} int main()
{
scanf("%d%d",&n,&m);
while(m--)
{
int k,a,b;scanf("%d",&k);
for(int i=;i<=k;i++)
{
scanf("%d",&b);
if(i!=) add(a,b),add(b,a);
a=b;
}
}
Dfs();
printf("%d\n",ans);
return ;
}
bzoj1023【SHOI2008】cactus仙人掌图的更多相关文章
- bzoj千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图
http://www.lydsy.com/JudgeOnline/problem.php?id=1023 dp[x] 表示以x为端点的最长链 子节点与x不在同一个环上,那就是两条最长半链长度 子节点与 ...
- BZOJ1023:[SHOI2008]cactus仙人掌图(圆方树,DP,单调队列)
Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus). 所谓简单回路就是指在图上不重复经过任何一个顶点 ...
- BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌dp)
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3467 Solved: 1438[Submit][Status][Discuss] Descripti ...
- BZOJ1023[SHOI2008]cactus仙人掌图 【仙人掌DP】
题目 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌 图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路. 举例来说 ...
- BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌)
Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的 ...
- [bzoj1023][SHOI2008]cactus 仙人掌图 (动态规划)
Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回 ...
- bzoj1023: [SHOI2008]cactus仙人掌图
学习了一下圆方树. 圆方树是一种可以处理仙人掌的数据结构,具体见这里:http://immortalco.blog.uoj.ac/blog/1955 简单来讲它是这么做的:用tarjan找环,然后对每 ...
- 2018.10.29 bzoj1023: [SHOI2008]cactus仙人掌图(仙人掌+单调队列优化dp)
传送门 求仙人掌的直径. 感觉不是很难. 分点在环上面和不在环上分类讨论. 不在环上直接树形dpdpdp. 然后如果在环上讨论一波. 首先对环的祖先有贡献的只有环上dfsdfsdfs序最小的点. 对答 ...
- bzoj1023 [SHOI2008]cactus仙人掌图 & poj3567 Cactus Reloaded——求仙人掌直径
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1023 http://poj.org/problem?id=3567 仙人掌!直接模仿 ...
- bzoj千题计划224:bzoj1023: [SHOI2008]cactus仙人掌图
又写了一遍,发出来做个记录 #include<cstdio> #include<algorithm> #include<iostream> using namesp ...
随机推荐
- 基于arcgis api for js高速公路智能化智慧公路养护WebGIS开源系统
伴随着高速公路建设进程加快,其涉及信息量增大.类型多样.地点分布广,传统的信息管理方式已不适应公路建设迅速发展的需要,而目前能对高速公路在设计.施工.养护等阶段的各类信息综合进行管理的信息系统尚较少见 ...
- 01_5_Struts_ActionMethod_DMI_动态方法调用
01_5_Struts_ActionMethod_DMI_动态方法调用 1. ActionMethod_DMI_动态方法调用 Action执行的时候并不一定要执行execute()方法 可以在配置文件 ...
- *运算和&运算
/* &:取地址运算符 *:指针运算符(或称为间接运算符),取指针所指向的对象的内容 */ int a,b; int *pointer_1, *pointer_2; pointer_1 = & ...
- 【思维题 线段树】cf446C. DZY Loves Fibonacci Numbers
我这种maintain写法好zz.考试时获得了40pts的RE好成绩 In mathematical terms, the sequence Fn of Fibonacci numbers is de ...
- Vue中引入TradingView制作K线图
**前言: 本文使用的是1.10版本 , 可通过TradingView.version()查看当前版本. 附上开发文档地址:https://zlq4863947.gitbooks.i...** 一.修 ...
- html5音频audio对象封装成vue组件的方式调用以及setTimeout如何在vue2生效 (vue2正在熟悉中,ajax还是用jQuery来写舒服些,里面含有一些php写法可略过) 此网页应用在PC不考虑手机端
// vue2 组件封装如下: <template> <div> <div><!--vue element 组件的引用 Switch 开关 不懂请自行百度(重 ...
- Python 变量作用域 LEGB (上)—— Local,Global,Builtin
Python 变量作用域的规则是 LEGB LEGB含义解释:L —— Local(function):函数内的名字空间E —— Enclosing function locals:外部嵌套函数的名字 ...
- 求数组中两两相加等于20的组合(Python实现)
题目 求数组中两两相加等于20的组合. 例:给定一个数组[1, 7, 17, 2, 6, 3, 14],这个数组中满足条件的有两对:17+3=20, 6+14=20. 解析 分为两个步骤: 先采用堆排 ...
- INDEX && PRIMARY KEY && UNIQUE KEY
When I have do some sql tody, some confusion come up to me. Its about the index && PRIMARY K ...
- UVa 11695 树的直径 Flight Planning
题意: 给出一棵树,删除一条边再添加一条边,求新树的最短的直径. 分析: 因为n比较小(n ≤ 2500),所以可以枚举删除的边,分裂成两棵树,然后有这么一个结论: 合并两棵树后得到的新树的最短直径为 ...