洛谷P4244 [SHOI2008]仙人掌图 II
首先不考虑带环的仙人掌,如果只是一棵普通的树,可以通过dp求每棵子树中的最长链和次长链求树的直径。
那么如果dfs的时候遇到了环,应该用环上的两点挂着的最长链加上两点间的距离来更新树的直径,并用环上一点的最长链加上它到环的根的距离来更新环的根的最长链。
选择环上两点来更新直径,为了考虑到所有选择,将环断开并拷贝一份新的衔接在后面,形成长为二倍的串。用dp[i]+dp[j]+j-i(i、j为在串中位置)更新直径,单调队列维护单调递减的dp[i]-i,并且如果当前点和队头的距离超过半个环就队头出队。
dfs的时候注意只用low[v]>dfn[u]的v来更新直径和u的最长链,判断是否有环的时候也注意让环的根成为环中深度最浅的,即判断dfn[v]>dfn[u],使u成为环的根,v为环的最后一个点。
#include<iostream>
#include<cstdio>
using namespace std;
const int N=;
int n,m,dp[N],ans,dis[N];
int ver[],Next[],head[N],tot,f[N];
void add(int x,int y){
ver[++tot]=y;
Next[tot]=head[x];
head[x]=tot;
}
int tim,dfn[N],low[N],a[*N],pos[*N],q[*N];
void solve(int x,int y){
int cnt=dis[y]-dis[x]+;
for(int i=y;i!=x;i=f[i]){
a[cnt--]=i;
}
a[cnt]=x;
cnt=dis[y]-dis[x]+;
for(int i=;i<=cnt;i++){
a[i+cnt]=a[i];
}
int l=,r=;
pos[]=,q[]=dp[a[]]-;
for(int i=;i<=*cnt;i++){
while(i-pos[l]>cnt/&&l<=r)l++;
ans=max(ans,q[l]+dp[a[i]]+i);
while(l<=r&&q[r]<=dp[a[i]]-i)r--;
q[++r]=dp[a[i]]-i;
pos[r]=i;
}
for(int i=;i<=cnt;i++){
dp[x]=max(dp[x],dp[a[i]]+min(i-,cnt-i+));
}
}
void dfs(int x,int fa){
dfn[x]=low[x]=++tim;
f[x]=fa;
for(int i=head[x];i;i=Next[i]){
int y=ver[i];
if(y==fa)continue;
if(!dfn[y]){
dis[y]=dis[x]+;
dfs(y,x);
low[x]=min(low[x],low[y]);
}
else low[x]=min(low[x],dfn[y]);
if(dfn[x]<low[y]){
ans=max(ans,dp[x]+dp[y]+);
dp[x]=max(dp[x],dp[y]+);
}
}
for(int i=head[x];i;i=Next[i]){
int y=ver[i];
if(y==fa)continue;
if(f[y]!=x&&dfn[y]>dfn[x]){
solve(x,y);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,k,lst,x;i<=m;i++){
scanf("%d",&k);
lst=;
while(k--){
scanf("%d",&x);
if(lst){
add(lst,x),add(x,lst);
}
lst=x;
}
}
dis[]=;
dfs(,);
printf("%d",ans);
return ;
}
洛谷P4244 [SHOI2008]仙人掌图 II的更多相关文章
- 洛谷 P4244 [SHOI2008]仙人掌图 II 解题报告
P4244 [SHOI2008]仙人掌图 II 题目背景 题目这个II是和SHOI2006的仙人掌图区分的,bzoj没有. 但是实际上还是和bzoj1023是一个题目的. 题目描述 如果某个无向连通图 ...
- P4244 [SHOI2008]仙人掌图 II
传送门 仙人掌直径,以前好像模拟赛的时候做到过一道基环树的直径,打了个很麻烦的然而还错了--今天才发现那就是这个的弱化版啊-- 如果是树的话用普通的dp即可,记\(f[u]\)表示\(u\)往下最长能 ...
- [SHOI2008]仙人掌图 II——树形dp与环形处理
题意: 给定一个仙人掌,边权为1 距离定义为两个点之间的最短路径 直径定义为距离最远的两个点的距离 求仙人掌直径 题解: 类比树形dp求直径. f[i]表示i向下最多多长 处理链的话,直接dp即可. ...
- [SHOI2008]仙人掌图
[SHOI2008]仙人掌图 LG传送门 还不会仙人掌的同学可以看看我对仙人掌知识的一些梳理. 题意就是求仙人掌的直径,直径定义为图中最短路径最长的两点间的最短路径长度. 按照套路,先考虑求树的直径我 ...
- 洛谷 P2616 [USACO10JAN]购买饲料II Buying Feed, II
洛谷 P2616 [USACO10JAN]购买饲料II Buying Feed, II https://www.luogu.org/problemnew/show/P2616 题目描述 Farmer ...
- 洛谷 P1182 数列分段 Section II
洛谷 P1182 数列分段 Section II 洛谷传送门 题目描述 对于给定的一个长度为N的正整数数列A-iA−i,现要将其分成M(M≤N)M(M≤N)段,并要求每段连续,且每段和的最大值最小. ...
- 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)
洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...
- 洛谷P1288 取数游戏II(博弈)
洛谷P1288 取数游戏II 先手必胜的条件需要满足如下中至少 \(1\) 条: 从初始位置向左走到第一个 \(0\) 的位置,经过边的数目为偶数(包含 \(0\) 这条边). 从初始位置向右走到第一 ...
- Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)
题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...
随机推荐
- 求N!中素数的个数
int degree_in_fact(int n, int x)//求n!中素数x的次数 { if(m) return degree_in_fact(n/x,x)+n/x; ; }
- Integer 类和 int 基本数据类型的区别
public static void main(String[] args) { Integer i = 10; Integer j = 10; System.out.println(i == j); ...
- java获取服务器路径
java获取服务器一些信息的方法(服务器地址/相对路径/端口/项目名字 request.getServletContext().getRealPath("/") 获取项目所在服务 ...
- 5.1_Spring Boot2.x安装Docker
1.简介 Docker是一个开源的应用容器引擎:是一个轻量级容器技术: Docker 是一个开源的应用容器引擎,基于Go 语言并遵从Apache2.0协议开源.Docker 可以让开发者打包他们的应用 ...
- telnet- Linux必学的60个命令
1.作用 telnet表示开启终端机阶段作业,并登入远端主机.telnet是一个Linux命令,同时也是一个协议(远程登陆协议). 2.格式 telnet [-8acdEfFKLrx][-b][-e] ...
- 记mysql 启动不了了的解决方法
系统: centos7 本地的环境,mysql启动不了,查看 /var/log/mysqld.log 有以下内容 2018-12-24T08:05:38.090527Z 0 [Warning] TIM ...
- leetcode-第5周双周赛-1135-最低成本联通所有城市
方法一: class Solution: def minimumCost(self, N: int, conections: List[List[int]]) -> int: def find( ...
- JUC 一 Callable
java.util.concurrent.Callable是一个泛型接口,只有一个call()方法 Callable和Runnable的区别 Callable使用call()方法,Runnable使用 ...
- JWT生成token
1.JWT简介 JSON Web Token 简称JWT.一个JWT实际上就是一个字符串,它由三部分组成,头部.载荷与签名.JWT生成的token是这样的 2.Json Web Token(JWT)生 ...
- js 手机号加密 中间星号表示
var tel = String(this.memberMsg.phoneNo); var dh=tel.substr(0,3)+"******"+tel.substr(8); r ...