[SHOI2008]cactus仙人掌图 (tarjan + dp)
来源:互联网 发布:艾欧尼亚30级账号淘宝 编辑:程序博客网 时间:2024/05/20 21:44
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,你的任务是求出给定的仙人图的直径。
早就开始做了。。。最近 czm 提起才想到。。。我觉得这是一道很好的题目。。。
首先求点双连通分量,然后对于每一个环 dp,可能的答案为 max{dis[i] + dis'[j], dis[x] + dist(x, y) + dis[y]}, dis 表示搜索树向下的最长路,dis‘表示第二长路(临时变量记之即可),dist(x, y) 表示仙人掌环上两点间的最短距离。
dp 就单(Ou)调(Shao)队列水过了。。。tarjan 什么的也就水过了。。。
然后爆栈什么的调了我一两个小时。。。最后删掉 dfs 中 3 个临时变量才过。。。
bzoj rank 10,貌似不是很颓。。。
Code :
#include <cstdio>#include <cstdlib>#include <cstring>#include <map>#include <set>#include <queue>#include <algorithm>using namespace std;#define FOR(i, j, k) for (i = (j); i <= (k); ++ i)#define ROF(i, j, k) for (i = (j); i >= (k); -- i)#define FER(i, j, k) for (i = j[k]; i; i = i->n)#define maxn 50005struct da{int t; da * n;};da das[maxn * 4], * adj = das + 1, * edge[maxn];int n, m, dfnn, tot, ans, i, j, k;int dfn[maxn], low[maxn], dis[maxn];da * sta[maxn * 2], ** top = sta;int a[maxn * 2], q[maxn * 2], h, t;void up(int & i, int j) {if (j > i) i = j;}void down(int & i, int j) {if (j < i) i = j;}void solve(int k){int i; q[h = t = 1] = 1;FOR (i, 2, tot){while (i - q[h] > k) ++ h;up(ans, dis[a[q[h]]] - q[h] + dis[a[i]] + i);while (h <= t && dis[a[i]] - i > dis[a[q[t]]] - q[t]) -- t;q[++ t] = i;}}void dfs(int u, int fa){da * e; int l = 0;dfn[u] = low[u] = ++ dfnn;FER (e, edge, u) if (e->t != fa)if (dfn[e->t]) down(low[u], dfn[e->t]);else{* (++ top) = e, dfs(e->t, u), down(low[u], low[e->t]);if (low[e->t] > dfn[u]){-- top;if (dis[e->t] + 1 > dis[u])l = dis[u], dis[u] = dis[e->t] + 1;else if (dis[e->t] + 1 > l)l = dis[e->t] + 1;}else if (low[e->t] == dfn[u]){tot = j = 0;do a[++ tot] = (* top)->t; while (* (top --) != e);FOR (i, 1, tot){up(j, dis[a[i]] + min(i, tot + 1 - i));a[i + tot + 1] = a[i];}a[++ tot] = u, k = tot >> 1, tot = (tot << 1) - 1;solve(k);if (j > dis[u]) l = dis[u], dis[u] = j;else if (j > l) l = j;}}up(ans, l + dis[u]);}void link(int i, int j){* (++ adj) = (da) {j, edge[i]}, edge[i] = adj;* (++ adj) = (da) {i, edge[j]}, edge[j] = adj;}int main(){freopen("cactus.in", "r", stdin);freopen("cactus.out", "w", stdout);int u, v;scanf("%d%d", & n, & m);FOR (i, 1, m){scanf("%d%d", & k, & u);FOR (j, 2, k) scanf("%d", & v), link(u, v), u = v;}dfs(1, 0);printf("%d\n", ans);return 0;}
- [SHOI2008]cactus仙人掌图 (tarjan + dp)
- BZOJ1023: [SHOI2008]cactus仙人掌图(单调队列优化DP)
- 【DP】 BZOJ 1023: [SHOI2008]cactus仙人掌图
- [BZOJ1023][SHOI2008[Cactus仙人掌]][Tarjan+单调队列+树形DP]
- BZOJ 1023 SHOI2008 cactus仙人掌图 仙人掌DP
- [BZOJ1023] [SHOI2008]cactus仙人掌图 && 仙人掌DP+单调队列
- [BZOJ1023][SHOI2008][仙人掌直径][队列优化DP]cactus仙人掌图
- 【SHOI2008】【BZOJ1023】cactus仙人掌图
- 【bzoj1023】[SHOI2008]cactus仙人掌图
- 1023: [SHOI2008]cactus仙人掌图
- bzoj1023: [SHOI2008]cactus仙人掌图
- BZOJ1023 [SHOI2008]cactus仙人掌图
- bzoj1023: [SHOI2008]cactus仙人掌图
- 1023: [SHOI2008]cactus仙人掌图
- bzoj1023 [SHOI2008]cactus仙人掌图
- BZOJ1023: [SHOI2008]cactus仙人掌图
- bzoj1023 [SHOI2008]cactus仙人掌图 树形DP+单调队列
- HDU 3594 Cactus (仙人掌图、Tarjan)
- CLisp 27:处理正则表达式regexp
- android:layout_gravity和android:gravity属性的区别
- 分享JAVA开发者最常去的20个国外英文网站
- NYOJ-14:会场安排问题
- Public key for *.rpm is not installed
- [SHOI2008]cactus仙人掌图 (tarjan + dp)
- Status Code Definitions
- java函数参数默认值
- JNI对HAL的封装
- ubuntu 12.04 通过virsh创建lxc container碰到问题及解决方法
- Ehcache配置
- 基于数据仓库和维度转换技术的广东电信公话IC话机话务动态分析系统
- 把myeclipse项目转到eclipse下的奇葩问题与解决
- Service