SHOI2008仙人掌图(tarjan+dp)
Solution
好题啊没的说。
本题需要求出仙人掌的直径,但仙人掌是一个带有简单环的一张图无法直接用树形dp求解,但它有一个好东西就是没有类似环套环的东西,所以我们在处理时就方便了一些。
思路:tarjan找环,对于不在环上的边或点,树形dp求解,对于每个环,dp求解(单调队列优化),
下面主要说一下代码的实现,
void tarjan(int u,int ff)
{
dfn[u]=low[u]=++top;
deep[u]=deep[ff]+;
for(int i=head[u];i;i=an[i].n)
if(an[i].to!=ff)
{
int v=an[i].to;
if(!dfn[v])
{
fa[v]=u;
tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else low[u]=min(low[u],dfn[v]);
if(dfn[u]<low[v])
{
ans=max(ans,f[u]+f[v]+);
f[u]=max(f[v]+,f[u]);
}
}
for(int i=head[u];i;i=an[i].n)
if(an[i].to!=ff&&fa[an[i].to]!=u&&dfn[an[i].to]>dfn[u])
ddpp(u,an[i].to);
}
这里是tarjan找环的部分,和普通的tarjan不一样的是,由于我们不用缩点并且仙人掌图没有横叉边,所以并不用开栈存点,当dfn[u]<low[v]时,说明这条边不在环上,可以用树形dp,下面用来判断当u
是环上一点并且是环上点中dfn序最小的点,这是就可以进行dp了(这是为了重)。
inline void ddpp(int s,int t)
{
int len=deep[t]-deep[s]+,te=len;
for(int i=t;i!=s;i=fa[i])
c[te--]=i;
c[]=s;
for(int i=;i<=len;++i)
c[i+len]=c[i];
int h=t=;q[h]=;
for(int i=;i<=len*;++i)
{
while(h<=t&&(i-q[h])>len/)h++;
if(h<=t)ans=max(ans,f[c[q[h]]]+f[c[i]]+i-q[h]);
while(h<=t&&f[c[q[t]]]-q[t]<=f[c[i]]-i)t--;
q[++t]=i;
}
for(int i=;i<=len;++i)
f[s]=max(f[s],f[c[i]]+min(len-i+,i-));
}
单调队列优化dp,用到了断环成链的技巧,要注意dp结束后要用环上所有点来更新s点,因为除了s点外其他点以后都没有用了,但s点还要向上更新,这步操作相当于把环缩成一个点。
完整代码
#include<iostream>
#include<cstdio>
#define N 50009
#define M 2000009
using namespace std;
int dfn[N],low[N],ans,deep[N],c[N<<],q[N<<],f[N],tot,head[N],top,fa[N],u,v,n,m,k;
struct ef
{
int n,to;
}an[M];
inline void add(int u,int v)
{
an[++tot].n=head[u];
an[tot].to=v;
head[u]=tot;
}
inline void ddpp(int s,int t)
{
int len=deep[t]-deep[s]+,te=len;
for(int i=t;i!=s;i=fa[i])
c[te--]=i;
c[]=s;
for(int i=;i<=len;++i)
c[i+len]=c[i];
int h=t=;q[h]=;
for(int i=;i<=len*;++i)
{
while(h<=t&&(i-q[h])>len/)h++;
if(h<=t)ans=max(ans,f[c[q[h]]]+f[c[i]]+i-q[h]);
while(h<=t&&f[c[q[t]]]-q[t]<=f[c[i]]-i)t--;
q[++t]=i;
}
for(int i=;i<=len;++i)
f[s]=max(f[s],f[c[i]]+min(len-i+,i-));
}
void tarjan(int u,int ff)
{
dfn[u]=low[u]=++top;
deep[u]=deep[ff]+;
for(int i=head[u];i;i=an[i].n)
if(an[i].to!=ff)
{
int v=an[i].to;
if(!dfn[v])
{
fa[v]=u;
tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else low[u]=min(low[u],dfn[v]);
if(dfn[u]<low[v])
{
ans=max(ans,f[u]+f[v]+);
f[u]=max(f[v]+,f[u]);
}
}
for(int i=head[u];i;i=an[i].n)
if(an[i].to!=ff&&fa[an[i].to]!=u&&dfn[an[i].to]>dfn[u])
ddpp(u,an[i].to);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;++i)
{
scanf("%d%d",&k,&u);
for(int j=;j<k;++j)
{
scanf("%d",&v);
add(u,v),add(v,u);
u=v;
}
}
tarjan(,);
cout<<ans;
return ;
}
SHOI2008仙人掌图(tarjan+dp)的更多相关文章
- 洛谷 P4244 [SHOI2008]仙人掌图 II 解题报告
P4244 [SHOI2008]仙人掌图 II 题目背景 题目这个II是和SHOI2006的仙人掌图区分的,bzoj没有. 但是实际上还是和bzoj1023是一个题目的. 题目描述 如果某个无向连通图 ...
- [SHOI2008]仙人掌图
[SHOI2008]仙人掌图 LG传送门 还不会仙人掌的同学可以看看我对仙人掌知识的一些梳理. 题意就是求仙人掌的直径,直径定义为图中最短路径最长的两点间的最短路径长度. 按照套路,先考虑求树的直径我 ...
- bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列
1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1141 Solved: 435[Submit][ ...
- BZOJ1023:[SHOI2008]仙人掌图——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1023 Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple ...
- [SHOI2008]仙人掌图 II——树形dp与环形处理
题意: 给定一个仙人掌,边权为1 距离定义为两个点之间的最短路径 直径定义为距离最远的两个点的距离 求仙人掌直径 题解: 类比树形dp求直径. f[i]表示i向下最多多长 处理链的话,直接dp即可. ...
- Luogu 4244 [SHOI2008]仙人掌图
BZOJ 1023 如果我们把所有的环都缩成一个点,那么整张图就变成了一棵树,我们可以直接$dp$算出树的直径. 设$f_x$表示$x$的子树中最长链的长度,那么对于$x$的每一个儿子$y$,先用$f ...
- P4244 [SHOI2008]仙人掌图 II
传送门 仙人掌直径,以前好像模拟赛的时候做到过一道基环树的直径,打了个很麻烦的然而还错了--今天才发现那就是这个的弱化版啊-- 如果是树的话用普通的dp即可,记\(f[u]\)表示\(u\)往下最长能 ...
- BZOJ1023 SHOI2008 仙人掌图 仙人掌、单调队列
传送门 求仙人掌的直径,可以由求树的直径进行拓展,只需要在环上特殊判断. 沿用求树的直径的DP,对于一条不在任何环内的边,直接像树的直径一样转移,然后考虑环的影响. 设环长为\(cir\),在\(df ...
- 【题解】SHOI2008仙人掌图
本质上还是树形dp.建立圆方树,遇到圆点的时候直接求(和树形dp一样即可),遇到方点做中转点的时候要考虑会从圆的另一侧通过(需满足最短路径的原则).原本是对于圆上的点进行 \(n^{2}\) 的匹配, ...
随机推荐
- Postman的Post请求方式的四种类型的数据
1. form-data 就是http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开.既可以上传键值对,也可以上传文件.当上传的字段是文件时 ...
- MT4用EA测试历史数据时日志出现:stopped because of stop out
今天用嘉盛的MT4测试一个EA,谁知道才走了十几天数据就完 了,看结果本金也没亏完啊,才亏了一半,而且我测的是1年的时间. 查看日志一有条警告:stopped because of stop out, ...
- PS中如何把图片颜色加到字体上去
1.在PS中的图层中,将图片置于文字层的上方,同时按ctrl+alt+g键,这样就将文字范围以外的图像给剪切掉了.见附图下方的效果. 2.最终效果如下图: 参见:https://zhidao.baid ...
- python学习笔记(10)--组合数据类型(集合类型)
集合类型 集合是多个元素的无序组合,每个元素唯一,不存在相同类型,每个元素是不可变类型.用{}表示,元素间用逗号分隔.建立结合类型用{},或set函数,如果是空集合必须用set. >>&g ...
- js auto hover button & html5 button autofocus
js auto hover button & html5 button autofocus input // html 5 <input name="myinput" ...
- Fetch API & Delete & HTTP Methods
Fetch API & Delete & HTTP Methods vue https://developer.mozilla.org/en-US/docs/Web/API/Fetch ...
- layui内部使用jQuery
layui是基于jQuery的框架,本身自带jQuery 根据官方推荐,是使用自带的好一点 这里记一下内部使用jQuery的方法: layui.use('jquery', function(){ va ...
- C-Lodop提示“网页还没下载完毕,请稍等一下再操作.”
该提示在Lodop旧版本中是: 提示"WebSocket没准备好,点确定继续",提示“C-Lodop没准备好”,新版本修改了该提示的描述“网页还没下载完毕,请稍等一下再操作.”,让 ...
- 当对具体的一条记录进行操作时候 需要传递该记录的id
- JAVA-Web 百度编辑器,修改默认大小
百度UEditor富文本编辑器-设置默认字体.字号.行间距及添加字体种类 如果这个还不能改变大小了,找一下在文件夹UEditor--css--中default.css文件,搜索出红色部分: grid_ ...