[SHOI2008]仙人掌图 II——树形dp与环形处理
题意:
给定一个仙人掌,边权为1
距离定义为两个点之间的最短路径
直径定义为距离最远的两个点的距离
求仙人掌直径
题解:
类比树形dp求直径。
f[i]表示i向下最多多长
处理链的话,直接dp即可。
处理环的话,类似点双tarjan,把环上的点都拉出来。
先考虑拼接更新答案。断环成链复制一倍,为了保证最短路,答案必须只能是f[i]+f[j]+i-j (i-len/2<=j<i)
单调队列优化。
直接i-j即可,另一半的绕环会在复制后的那里处理。
然后更新f[x],直接找环上其他的元素,距离就是两段距离的较小值。
因为tarjan本质上是一棵dfs树,所以处理环的时候元素都是x的儿子,儿子们的f必然已经处理。
tarjan点双时注意:

下面的写法是错误的。
因为,点双时的割点可能属于多个dcc,所以可能y不和x紧挨着存储。会弹出多余的东西。

黑色是仙人掌,红色是dfs树。A,B是V-DCC
可能访问x之后,先访问了A,因为father的dfn小,所以不能弹栈。A的红色部分在栈里保存。
然后从y进入,访问B。发现访问完了之后,可以弹栈,
如果是第二种写法,那么会等到栈顶是x才停止,那么会把A中的点也弹出来。
根本知道弹出来的是什么。。。。
第一种的话,会在弹出y之后停止。没有问题。
症结就因为x属于两个V-DCC
还要注意:
多次用queue,必须保证在l<=r时才能更新答案。
if(l<=r) ans=max(ans,f[mem[i]]+i+f[mem[q[l]]]-q[l]);
代码:
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=+;
int n,m;
struct node{
int nxt,to;
}e[*N];
int hd[N],cnt;
void add(int x,int y){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
hd[x]=cnt;
}
int dfn[N],df,low[N];
int f[N];
int q[N],l,r;
int ans;
int sta[N],top,len;
int mem[*N],num;
void wrk(int x){
len=num;
for(reg i=;i<=num;++i) mem[i+num]=mem[i],ans=max(ans,f[mem[i]]);
l=,r=;
for(reg i=;i<=*num;++i){
while(l<=r&&q[l]<i-len/) ++l;
if(l<=r) ans=max(ans,f[mem[i]]+i+f[mem[q[l]]]-q[l]);
while(l<=r&&f[mem[q[r]]]-q[r]<f[mem[i]]-i) --r;
q[++r]=i;
}
for(reg i=;i<=num;++i){
f[x]=max(f[x],f[mem[i]]+min(i-,num+-i));
}
}
void tarjan(int x){
//cout<<" tarjan "<<x<<" top "<<top<<endl;
dfn[x]=low[x]=++df;
sta[++top]=x;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(dfn[x]<=low[y]){//find V-dcc
num=;
mem[++num]=x;
int z;
do{
z=sta[top--];
mem[++num]=z;
}while(z!=y);
wrk(x);
}
}
else low[x]=min(low[x],dfn[y]);
}
}
int main(){
rd(n);rd(m);int k,x,y;
for(reg i=;i<=m;++i){
rd(k);rd(x);
for(reg j=;j<k;++j){
rd(y);add(x,y);add(y,x);x=y;
}
}
tarjan();
// for(reg i=1;i<=n;++i){
// cout<<i<<" : "<<f[i]<<endl;
// }
printf("%d",ans);
return ;
} }
int main(){
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/11/30 7:44:32
*/
[SHOI2008]仙人掌图 II——树形dp与环形处理的更多相关文章
- 洛谷 P4244 [SHOI2008]仙人掌图 II 解题报告
P4244 [SHOI2008]仙人掌图 II 题目背景 题目这个II是和SHOI2006的仙人掌图区分的,bzoj没有. 但是实际上还是和bzoj1023是一个题目的. 题目描述 如果某个无向连通图 ...
- SHOI2008仙人掌图(tarjan+dp)
Solution 好题啊没的说. 本题需要求出仙人掌的直径,但仙人掌是一个带有简单环的一张图无法直接用树形dp求解,但它有一个好东西就是没有类似环套环的东西,所以我们在处理时就方便了一些. 思路:ta ...
- P4244 [SHOI2008]仙人掌图 II
传送门 仙人掌直径,以前好像模拟赛的时候做到过一道基环树的直径,打了个很麻烦的然而还错了--今天才发现那就是这个的弱化版啊-- 如果是树的话用普通的dp即可,记\(f[u]\)表示\(u\)往下最长能 ...
- 洛谷P4244 [SHOI2008]仙人掌图 II
传送门 首先不考虑带环的仙人掌,如果只是一棵普通的树,可以通过dp求每棵子树中的最长链和次长链求树的直径. 那么如果dfs的时候遇到了环,应该用环上的两点挂着的最长链加上两点间的距离来更新树的直径,并 ...
- [SHOI2008]仙人掌图
[SHOI2008]仙人掌图 LG传送门 还不会仙人掌的同学可以看看我对仙人掌知识的一些梳理. 题意就是求仙人掌的直径,直径定义为图中最短路径最长的两点间的最短路径长度. 按照套路,先考虑求树的直径我 ...
- bzoj 4784: [Zjoi2017]仙人掌【tarjan+树形dp】
其实挺简单的但是没想出来---- 首先判断无解情况,即,一开始的图就不是仙人掌,使用tarjan判断如果一个点dfs下去有超过一个点比他早,则说明存在非简单环. 然后考虑dp,显然原图中已经属于某个简 ...
- BZOJ1023:[SHOI2008]仙人掌图——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1023 Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple ...
- Luogu 4244 [SHOI2008]仙人掌图
BZOJ 1023 如果我们把所有的环都缩成一个点,那么整张图就变成了一棵树,我们可以直接$dp$算出树的直径. 设$f_x$表示$x$的子树中最长链的长度,那么对于$x$的每一个儿子$y$,先用$f ...
- 【题解】SHOI2008仙人掌图
本质上还是树形dp.建立圆方树,遇到圆点的时候直接求(和树形dp一样即可),遇到方点做中转点的时候要考虑会从圆的另一侧通过(需满足最短路径的原则).原本是对于圆上的点进行 \(n^{2}\) 的匹配, ...
随机推荐
- HTTP与HTTPS介绍
文章大纲 一.HTTP和HTTPS的基本概念二.HTTP缺点三.HTTPS介绍四.免费HTTPS证书推荐 一.HTTP和HTTPS的基本概念 HTTP:是互联网上应用最为广泛的一种网络协议,是一个 ...
- [20190402]Library Cache mutex.txt
[20190402]Library Cache mutex.txt 1.环境:SCOTT@book> @ ver1PORT_STRING VERSION ...
- Oracle 查询权限视图
在Oracle中有很多用于查权限的视图,但很多人在需要查权限时会很困惑,不知道该用哪个视图去查,这里我列出几个常见的用于查权限的视图及其用法: 1DBA_ROLE_PRIVS 该视图主要有以下2个作用 ...
- angualr跨域访问配置
浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cn和b.cn是不同域),所以跨域就出现了: 简单的解释就是相同域名,端口相同,协议 ...
- 解决Linux系统下Mysql数据库中文显示成问号的问题
当我们将开发好的javaWEB项目部署到linux系统上,操作数据库的时候,会出现中文乱码问题,比如做插入操作,发现添加到数据库的数据中文出现论码,下面就将解决linux下mysql中文乱码问题! 打 ...
- 电信中兴F460光猫sendcmd命令
1.安装xshell后,使用命令行登陆root用户,root用户密码Zte521(湖北地区) 2.查看所有用户密码 sendcmd 1 DB p DevAuthInfo 3.打开网页登陆teleco ...
- jenkins安装详细教程
一.jenkins简介 jenkins是一个开源的软件项目,是基于java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 1.持续的软件版本 ...
- Docker: 构建Nginx,PHP,Tomcat基础镜像
Usage: docker build [OPTIONS] PATH | URL | - [flags] Options: -t, --tag list # 镜像名称 -f, --file strin ...
- it's time to change myself now (2018.10.31)
自16年从新屋熊职校毕业,入职深圳某厂从事云存储两年半了.两年半的时间很快,快的感觉一生都会飞快,两年多一直很忙,忙的几乎忘了自己是否正向改变过. 正向改变,or 积极改变,今年十一回家,与几个好友小 ...
- django url分发,视图,模板回顾
Django基础轮廓 MTV+controller 一 url分发系统: 1 简单使用 url(r'^articles/2003/$', views.special_case_2003), # spe ...