BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌dp)
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 3467 Solved: 1438
[Submit][Status][Discuss]
Description
如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌
图(cactus)。所谓简单回路就是指在图上不重复经过任何一个顶点的回路。
举例来说,上面的第一个例子是一张仙人图,而第二个不是——注意到它有三条简单回路:(4,3,2,1,6
,5,4)、(7,8,9,10,2,3,7)以及(4,3,7,8,9,10,2,1,6,5,4),而(2,3)同时出现在前两
个的简单回路里。另外,第三张图也不是仙人图,因为它并不是连通图。显然,仙人图上的每条边,或者是这张仙
人图的桥(bridge),或者在且仅在一个简单回路里,两者必居其一。定义在图上两点之间的距离为这两点之间最
短路径的距离。定义一个图的直径为这张图相距最远的两个点的距离。现在我们假定仙人图的每条边的权值都是1
,你的任务是求出给定的仙人图的直径。
Input
输入的第一行包括两个整数n和m(1≤n≤50000以及0≤m≤10000)。其中n代表顶点个数,我们约定图中的顶
点将从1到n编号。接下来一共有m行。代表m条路径。每行的开始有一个整数k(2≤k≤1000),代表在这条路径上
的顶点个数。接下来是k个1到n之间的整数,分别对应了一个顶点,相邻的顶点表示存在一条连接这两个顶点的边
。一条路径上可能通过一个顶点好几次,比如对于第一个样例,第一条路径从3经过8,又从8返回到了3,但是我们
保证所有的边都会出现在某条路径上,而且不会重复出现在两条路径上,或者在一条路径上出现两次。
Output
只需输出一个数,这个数表示仙人图的直径长度。
Sample Input
9 1 2 3 4 5 6 7 8 3
7 2 9 10 11 12 13 10
5 2 14 9 15 10 8
10 1
10 1 2 3 4 5 6 7 8 9 10
Sample Output
9
HINT
对第一个样例的说明:如图,6号点和12号点的最短路径长度为8,所以这张图的直径为8。
Source
仙人掌DP
对于这种题的套路就是先考虑只是一棵树的情况,再特判环上的情况
如果是裸的树,我们用$f[i]$表示$i$号节点对应的最长链的长度,然后枚举任意两个点之间的边,进行更新
如果出现了环怎么办?
考虑如果是在环上,同样是用环上的两点去更新的答案,
任意两点对答案的贡献为$f[i]+f[j]+dis(i,j)$,$dis(i,j)$表示$i,j$两点间的最短路径
在环上,任意两点间存在两条路径,此时有两种处理方法:
1.正着来一遍再倒着来一遍
2.拆环成链
然后用单调队列维护一下就行了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1e6 + , INF = 1e9 + ;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
struct Edge {
int u, v, nxt;
}E[MAXN << ];
int head[MAXN], num = ;
inline void AddEdge(int x, int y) {
E[num] = (Edge){x, y, head[x]};
head[x] = num++;
}
int N, M;
int fa[MAXN], dfn[MAXN], low[MAXN], Index, deep[MAXN];
int f[MAXN], ans = ;
int a[MAXN << ], Q[MAXN];
void DP(int x, int y) {
int tot = ;
for(int i = y; i != x; i = fa[i]) a[++tot] = i; a[++tot] = x;
reverse(a + , a + tot + );
for(int i = ; i <= tot; i++) a[i + tot] = a[i];
int h = , t =;
for(int i = ; i <= (tot << ); i++) {
while(h <= t && i - Q[h] > tot / ) h++;
if(h <= t) ans = max(ans, f[a[i]] + f[a[Q[h]]] + i - Q[h]);
while(h <= t && f[a[Q[t]]] - Q[t] < f[a[i]] - i) t--;
Q[++t] = i;
}
for(int i = y; i != x; i = fa[i])
f[x] = max(f[x], f[i] + min(deep[i] - deep[x], deep[y] - deep[i] + ));
}
void Tarjan(int x, int _fa) {
fa[x] = _fa; dfn[x] = low[x] = ++Index; deep[x] = deep[_fa] + ;
for(int i = head[x], v; i != -; i = E[i].nxt) {
if((v = E[i].v) == _fa) continue;
if(!dfn[v]) Tarjan(v, x), low[x] = min(low[x], low[v]);
else low[x] = min(low[x], dfn[v]);
if(dfn[x] < low[v]) ans = max(ans, f[x] + f[v] + ), f[x] = max(f[x], f[v] + );
//why is dfn?
if(fa[v] != x && dfn[v] > dfn[x])
DP(x, v);
}
}
int main() {
#ifdef WIN32
freopen("a.in", "r", stdin);
#else
#endif
memset(head, -, sizeof(head));
N = read(); M = read();
for(int i = ; i <= M; i++) {
int K = read(), pre = read();
for(int j = ; j <= K; j++) {
int now = read();
AddEdge(pre, now); AddEdge(now, pre), pre = now;
}
}
Tarjan(, );
printf("%d\n", ans);
return ;
}
BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌dp)的更多相关文章
- BZOJ1023:[SHOI2008]cactus仙人掌图(圆方树,DP,单调队列)
Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus). 所谓简单回路就是指在图上不重复经过任何一个顶点 ...
- BZOJ1023[SHOI2008]cactus仙人掌图 【仙人掌DP】
题目 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌 图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路. 举例来说 ...
- bzoj千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图
http://www.lydsy.com/JudgeOnline/problem.php?id=1023 dp[x] 表示以x为端点的最长链 子节点与x不在同一个环上,那就是两条最长半链长度 子节点与 ...
- BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌)
Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的 ...
- 2018.10.29 bzoj1023: [SHOI2008]cactus仙人掌图(仙人掌+单调队列优化dp)
传送门 求仙人掌的直径. 感觉不是很难. 分点在环上面和不在环上分类讨论. 不在环上直接树形dpdpdp. 然后如果在环上讨论一波. 首先对环的祖先有贡献的只有环上dfsdfsdfs序最小的点. 对答 ...
- [BZOJ1023][SHOI2008]cactus仙人掌图 DP
题目链接 套路就是先考虑一般的树上做法.求直径的dp的做法大家应该都会吧. 那么设\(dp[i]\)表示\(i\)的子树中的点到\(i\)的最大距离. 在dp的过程中 \[ ans=\max\{dp[ ...
- [bzoj1023][SHOI2008]cactus 仙人掌图 (动态规划)
Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回 ...
- bzoj1023: [SHOI2008]cactus仙人掌图
学习了一下圆方树. 圆方树是一种可以处理仙人掌的数据结构,具体见这里:http://immortalco.blog.uoj.ac/blog/1955 简单来讲它是这么做的:用tarjan找环,然后对每 ...
- bzoj1023 [SHOI2008]cactus仙人掌图 & poj3567 Cactus Reloaded——求仙人掌直径
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1023 http://poj.org/problem?id=3567 仙人掌!直接模仿 ...
随机推荐
- 实现绘制图形的ToolBar
给地图添加绘制图形的ToolBar还是有必要的,比较人性化的功能.图形的样式可以自己定制,也提供了朴实的默认样式.对 dojo 不太懂,出现了许许多多问题,真是蛋疼的一天啊.令人惊喜的是 ArcGis ...
- Python爬虫教程-22-lxml-etree和xpath配合使用
Python爬虫教程-22-lxml-etree和xpath配合使用 lxml:python 的HTML/XML的解析器 官网文档:https://lxml.de/ 使用前,需要安装安 lxml 包 ...
- 【Python】面向对象编程思想
概念 "笔"作为一个抽象的概念,可以被看成是一个类.而一支实实在在的笔,则是"笔"这种类型的对象. 一个类可以有属于它的函数,这种函数被称为类的"方法 ...
- angular2 ng build --prod 报错:Module not found: Error: Can't resolve './$$_gendir/app/app.module.ngfactory'
调试页面 ng serve 正常 ng build 也正常 ng build --prod 异常:Module not found: Error: Can't resolve './$$_gendir ...
- ROS Create a Catkin Workspace
Step1 : First, create the top level catkin workspace directory and a sub-directory named src (pronou ...
- ZT北大青鸟营业额超20亿到不值一提 衰落的背后
北大青鸟营业额超20亿到不值一提 衰落的背后 2013-10-18 08:18 王根旺 我要评论 (0) “北大青鸟是个悲剧!”说到曾经的IT培训业巨头,黑马导师.珍品网创始人曹允东惋惜道.在学大创 ...
- Python深入学习之《Fluent Python》 Part 1
Python深入学习之<Fluent Python> Part 1 从上个周末开始看这本<流畅的蟒蛇>,技术是慢慢积累的,Python也是慢慢才能写得优雅(pythonic)的 ...
- 不规矩的xml与JAVA对象互相转换的小技巧-使用Marshaller
摘要:将XML文档与JAVA对象互转是很常见的需求,如果XML定义很规整这很好实现.然而在现实中“不规矩”的XML可能更常见,Marshaller便无能为力了吗?下面是一个小技巧,调整一下思维便能重用 ...
- webConfig详细跳转配置.[转]
站更换域名,把旧域名用301指到新域名来. 从iis中设置url永久转向就可以,看上去很容易,用了一会儿才发现,参数都没有带上. 从微软网站上找到如下说明,果然好使: 重定向参考 (IIS 6.0,7 ...
- BZOJ5299:[CQOI2018]解锁屏幕(状压DP)
Description 使用过Android手机的同学一定对手势解锁屏幕不陌生.Android的解锁屏幕由3x3个点组成,手指在屏幕上画一条 线将其中一些点连接起来,即可构成一个解锁图案.如下面三个例 ...