传送门


求仙人掌的直径,可以由求树的直径进行拓展,只需要在环上特殊判断。

沿用求树的直径的DP,对于一条不在任何环内的边,直接像树的直径一样转移,然后考虑环的影响。

设环长为\(cir\),在\(dfs\)树上,环对应的链的链顶为\(top\),链底为\(bot\),也就是说返祖边为\((top,bot)\),点\(x\)在\(dfs\)树上的深度为\(dep_x\)。

在统计环上的点之间的转移和贡献之前,先把环上所有点的子仙人掌的贡献统计好。

环上的转移直接通过方程式\(dp_{top} \leftarrow dp_{u} + \min\{dep_u - dep_{top} , cir - dep_u + dep_{top}\}\)从所有点转移到链顶

考虑如何统计环上的贡献,相对来说是比较难的一部分。

对于在环上的两个点\(u,v(dep_u > dep_v)\),它们对答案的贡献为\(dp_u + dp_v + \min\{dep_u - dep_{v} , cir - dep_u + dep_{v}\}\)

我们考虑将\(dp_u +dp_v + dep_u - dep_v\)和\(dp_u + dp_v + cir + dep_v - dep_u\)的贡献分开计算。下面只说\(dp_u + dp_v + dep_u - dep_v\)的情况,另一种计算同理。

我们考虑按照深度从大往小加点,那么如果对于两个点\(i,j\)满足\(dep_i < dep_j \&\& dep_i + dp_i \geq dep_j + dp_j\),表示\(i\)相比于\(j\)能够对更多的点产生贡献,而且转移更优,那么\(j\)就是没有必要的了。可以发现转移满足单调队列优化的性质,使用单调队列优化转移即可。记得转移需要满足\(dep_u - dep_v < cir + dep_v - dep_u\),如果队首不满足这个条件需要删除。

#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;inline int read(){int a = 0;char c = getchar();bool f = 0;while(!isdigit(c) && c != EOF){if(c == '-')f = 1;c = getchar();}if(c == EOF)exit(0);while(isdigit(c)){a = a * 10 + c - 48;c = getchar();}return f ? -a : a;
}const int MAXN = 1e5 + 10;
struct Edge{int end , upEd;
}Ed[MAXN << 2];
int head[MAXN] , dp[MAXN] , dep[MAXN] , fa[MAXN] , ch[MAXN];
int N , M , cntEd , ans;
deque < int > q;inline void addEd(int a , int b){Ed[++cntEd].end = b;Ed[cntEd].upEd = head[a];head[a] = cntEd;
}void calc(int top , int bot){int cir = dep[bot] - dep[top] + 1 , p = bot;q.push_back(bot);do{ch[fa[p]] = p;p = fa[p];int t = q.front();if(dep[t] - dep[p] > cir - dep[t] + dep[p]){q.pop_front();t = q.front();}ans = max(ans , dep[t] - dep[p] + dp[t] + dp[p]);while(!q.empty() && dep[q.back()] + dp[q.back()] <= dep[p] + dp[p])q.pop_back();q.push_back(p);}while(p != top);q.clear();int p1 = top;p = bot;q.push_back(p1);while(cir - dep[p] + dep[top] <= dep[p] - dep[top])p = fa[p];do{p1 = ch[p1];p = ch[p];int t = q.front();ans = max(ans , cir + dep[t] - dep[p] + dp[t] + dp[p]);while(!q.empty() && dep[q.back()] + dp[q.back()] <= dep[p1] + dp[p1])q.pop_back();q.push_back(p1);}while(p != bot);q.clear();p = bot;while(p != top){dp[top] = max(dp[top] , dp[p] + min(dep[p] - dep[top] , cir + dep[top] - dep[p]));p = fa[p];}
}int dfs(int x , int p){fa[x] = p;dep[x] = dep[p] + 1;int t = 0;for(int i = head[x] ; i ; i = Ed[i].upEd)if(Ed[i].end != p)if(dep[Ed[i].end])if(dep[Ed[i].end] < dep[x])t = Ed[i].end;elsecalc(x , Ed[i].end);else{int q = dfs(Ed[i].end , x);if(!q){ans = max(ans , dp[x] + dp[Ed[i].end] + 1);dp[x] = max(dp[x] , dp[Ed[i].end] + 1);}elseif(q != x)t = q;}return t;
}int main(){
#ifndef ONLINE_JUDGEfreopen("in","r",stdin);//freopen("out","w",stdout);
#endifN = read();M = read();for(int i = 1 ; i <= M ; ++i){int L = read() , a = read();for(int i = 2 ; i <= L ; ++i){int b = read();addEd(a , b);addEd(b , a);a = b;}}dfs(1 , 0);cout << ans;return 0;
}

转载于:https://www.cnblogs.com/Itst/p/10287918.html

BZOJ1023 SHOI2008 仙人掌图 仙人掌、单调队列相关推荐

  1. Acwing 360. Freda的传呼机(仙人掌图重构,lca)

    为了随时与rainbow快速交流,Freda制造了两部传呼机.Freda和rainbow所在的地方有N座房屋.M 条双向光缆. 每条光缆连接两座房屋,传呼机发出的信号只能沿着光缆传递,并且传呼机的信号 ...

  2. 2018.10.29 bzoj1023: [SHOI2008]cactus仙人掌图(仙人掌+单调队列优化dp)

    传送门 求仙人掌的直径. 感觉不是很难. 分点在环上面和不在环上分类讨论. 不在环上直接树形dpdpdp. 然后如果在环上讨论一波. 首先对环的祖先有贡献的只有环上dfsdfsdfs序最小的点. 对答 ...

  3. BZOJ1023 [SHOI2008]仙人掌图

    Address BZOJ1023 洛谷P4244 Solution 第一次做仙人掌图. 主要难在环中 DP 值的处理. 注意题目中提到的性质: 仙人图上的每条边,或者是这张仙人图的桥,或者在且仅在一个 ...

  4. cactus仙人掌图【仙人掌圆方树+树形DP+单调队列】

    题目链接 BZOJ 1023 首先,圆方树是比较好想到的,维护直径,我们最方便的做法就是先让它变成一棵树,这里因为是仙人掌图,所以就用圆方树来构建. 再者,就是维护直径了,比较好想到的是非环上结点,就 ...

  5. BZOJ1023[SHOI2008]cactus仙人掌图 【仙人掌DP】

    题目 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌 图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路. 举例来说 ...

  6. BZOJ1023:[SHOI2008]仙人掌图——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1023 Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple ...

  7. BZOJ1023 [SHOI2008]cactus仙人掌图

    滚回第一页去了... 好吧,看了题解蒟蒻也写不粗来,怎么办捏? 看这个吧:Orz YDC巨巨:但是巨巨写的程序又不优美,于是程序Orz hzwer 其实这题的重点在于tarjan和单调队列dp里&qu ...

  8. [BZOJ]1023: [SHOI2008]cactus仙人掌图

    Time Limit: 1 Sec  Memory Limit: 162 MB Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这 ...

  9. bzoj 1023: [SHOI2008]cactus仙人掌图(仙人掌求直径)

    1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 3668  Solved: 1535 [Submi ...

  10. BZOJ 1023: [SHOI2008]cactus仙人掌图

    1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 2907  Solved: 1212 [Submi ...

最新文章

  1. linux入门(三)常见Linux指令及其用法
  2. 【LeetCode 剑指offer刷题】数组题2:57 有序数组中和为s的两个数(167 Two Sum II - Input array is sorted)...
  3. visual studio输入法打不了中文_目前比较满意的手机输入法方案:Gboard + 搜狗词库...
  4. ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车前后左右综合实验
  5. 通俗易懂量子计算的原理
  6. php上传文件到七牛云源码,laravel上传文件到七牛云存储
  7. java多线程论文_Java5 多线程之入门篇-论文
  8. 数的划分(信息学奥赛一本通-T1440)
  9. ArcEngine中多边形内外环的处理(转)
  10. 吴恩达点赞的deeplearning.ai课程总结
  11. 红米骁龙855旗舰关键细节曝光:256G ROM+GPU超频模式
  12. Membership、MembershipUser和Roles类
  13. HyperVolume多目标评价指标概述
  14. 区块链与java的应用开发_用 Java 开发一个区块链
  15. Mac安装Docker及使用
  16. 支付宝小程序的开发笔记
  17. Invalid use of SingleClientConnManager: connection still allocated解决方案
  18. meta分析 2. 固定效应和随机效应
  19. 游戏策划学习:笔试整理
  20. 【fk_index】外键中有无索引的区别

热门文章

  1. java中struts2框架,概述Java的struts2框架
  2. VHDL计算机硬件能直接执行吗,第5章 VHDL程序结构.ppt
  3. kafka创耳机_生产环境一键创建kafka集群
  4. 领域搜索算法 是什么 和遗传算法、模拟退火算法、禁忌搜索算法、模糊优化 算法、微粒群算法关系
  5. FISCO BCOS性能优化——工具篇
  6. ubuntu 卸载openjdk 安装java8 安装之后提示Command ‘java‘ not found
  7. Mybatis--关于插入数据后返回id的操作
  8. mysql 为什么性能不稳定_浅谈MySQL 数据库性能优化
  9. JavaSE基础——GUI编程(AWT)
  10. matlab有限域多项式除法_域上的多项式环(3) - 多项式同余理论