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

  1. 15 3
  2. 9 1 2 3 4 5 6 7 8 3
  3. 7 2 9 10 11 12 13 10
  4. 5 2 14 9 15 10
  5. 10 1
  6. 10 1 2 3 4 5 6 7 8 9 10

Sample Output

  1. 8
  2. 9

HINT

对第一个样例的说明:如图,6号点和12号点的最短路径长度为8,所以这张图的直径为8。

【注意】使用Pascal语言的选手请注意:你的程序在处理大数据的时候可能会出现栈溢出。

如果需要调整栈空间的大小,可以在程序的开头填加一句:{$M 5000000},其中5000000即指代栈空间的大小,请根据自己的程序选择适当的数值。

Solution

仙人掌的题目大多都是把树和环拆开来做

假设这个图是个树,那么就很简单,直接dp,设 \(f_u\) 代表节点 \(u\) 的子树中的一段在 \(u\) 的最长链,\(f_u=\max\{f_v+1\}\) ,转移的同时也用 \(f_u+f_v+1\) 更新答案

对于环,环上的每个点开始时记录的肯定是它们的外向树的最长链,那么环上两个点的贡献就是它们的外向树中的最长链加上这两个点在环上的短侧的距离。所以我们就可以在环上跑一遍dp,更新答案,同时再把 \(root\) 的答案更新就好了。对于环上的dp,我们可以用个单调队列,队列里只存在当前枚举点之前的距离小于等于环的一半的点,这样保证了环上两点的距离一定是短侧,那么更新答案的式子就是 \(f_{a[i]}+f_{a[j]}+i-j+1\) ,因为我们对于每个位置都要最大,那么我们就是要可以改变的 \(f_{a[j]}-j\) 最大,所以用单调队列维护。因为是个环,所以还要把环上的点复制一遍。

  1. #include<bits/stdc++.h>
  2. #define ui unsigned int
  3. #define ll long long
  4. #define db double
  5. #define ld long double
  6. #define ull unsigned long long
  7. const int MAXN=50000+10,MAXM=10000000+10;
  8. int n,m,ans,e,beg[MAXN],nex[MAXM<<1],to[MAXM<<1],DFN[MAXN],LOW[MAXN],a[MAXN<<1],cnt,Visit_Num,f[MAXN],fa[MAXN];
  9. std::deque<int> q;
  10. template<typename T> inline void read(T &x)
  11. {
  12. T data=0,w=1;
  13. char ch=0;
  14. while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
  15. if(ch=='-')w=-1,ch=getchar();
  16. while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
  17. x=data*w;
  18. }
  19. template<typename T> inline void write(T x,char ch='\0')
  20. {
  21. if(x<0)putchar('-'),x=-x;
  22. if(x>9)write(x/10);
  23. putchar(x%10+'0');
  24. if(ch!='\0')putchar(ch);
  25. }
  26. template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
  27. template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
  28. template<typename T> inline T min(T x,T y){return x<y?x:y;}
  29. template<typename T> inline T max(T x,T y){return x>y?x:y;}
  30. inline void insert(int x,int y)
  31. {
  32. to[++e]=y;
  33. nex[e]=beg[x];
  34. beg[x]=e;
  35. }
  36. inline void loop(int root,int x)
  37. {
  38. while(!q.empty())q.pop_front();
  39. a[cnt=1]=x;
  40. for(register int i=x;i!=root;i=fa[i])a[++cnt]=fa[i];
  41. for(register int i=1;i<=cnt;++i)a[i+cnt]=a[i];
  42. for(register int i=1;i<=(cnt<<1);++i)
  43. {
  44. while(!q.empty()&&i-q.front()>(cnt>>1))q.pop_front();
  45. if(!q.empty())chkmax(ans,f[a[i]]+f[a[q.front()]]+i-q.front());
  46. while(!q.empty()&&f[a[i]]-i>f[a[q.back()]]-q.back())q.pop_back();
  47. q.push_back(i);
  48. }
  49. for(register int i=1;i<cnt;++i)chkmax(f[root],f[a[i]]+min(cnt-i,i));
  50. }
  51. inline void Tarjan(int x,int p)
  52. {
  53. DFN[x]=LOW[x]=++Visit_Num;fa[x]=p;
  54. for(register int i=beg[x];i;i=nex[i])
  55. if(to[i]==p)continue;
  56. else
  57. {
  58. if(!DFN[to[i]])Tarjan(to[i],x),chkmin(LOW[x],LOW[to[i]]);
  59. else if(DFN[to[i]]<DFN[x])chkmin(LOW[x],DFN[to[i]]);
  60. if(LOW[to[i]]>DFN[x])chkmax(ans,f[x]+f[to[i]]+1),chkmax(f[x],f[to[i]]+1);
  61. }
  62. for(register int i=beg[x];i;i=nex[i])
  63. if(to[i]==p)continue;
  64. else if(fa[to[i]]!=x&&DFN[to[i]]>DFN[x]&&LOW[to[i]]<=DFN[x])loop(x,to[i]);
  65. }
  66. int main()
  67. {
  68. while(scanf("%d%d",&n,&m)!=EOF)
  69. {
  70. ans=0;e=0;
  71. for(register int i=1;i<=n;++i)beg[i]=f[i]=DFN[i]=LOW[i]=0;
  72. for(register int i=1;i<=m;++i)
  73. {
  74. int k,u;read(k);read(u);
  75. for(register int j=2,v;j<=k;++j,u=v)read(v),insert(u,v),insert(v,u);
  76. }
  77. for(register int i=1;i<=n;++i)
  78. if(!DFN[i])Tarjan(i,0);
  79. printf("%d\n",ans);
  80. }
  81. return 0;
  82. }

【刷题】BZOJ 1023 [SHOI2008]cactus仙人掌图的更多相关文章

  1. bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列

    1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1141  Solved: 435[Submit][ ...

  2. BZOJ 1023: [SHOI2008]cactus仙人掌图 | 在仙人掌上跑DP

    题目: 求仙人掌直径 http://www.lydsy.com/JudgeOnline/problem.php?id=1023 题解: 首先给出仙人掌的定义:满足所有的边至多在一个环上的无向联通图 我 ...

  3. bzoj 1023: [SHOI2008]cactus仙人掌图 2125: 最短路 4728: 挪威的森林 静态仙人掌上路径长度的维护系列

    %%% http://immortalco.blog.uoj.ac/blog/1955 一个通用的写法是建树,对每个环建一个新点,去掉环上的边,原先环上每个点到新点连边,边权为点到环根的最短/长路长度 ...

  4. bzoj 1023 [SHOI2008]cactus仙人掌图 ( poj 3567 Cactus Reloaded )——仙人掌直径模板

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1023 http://poj.org/problem?id=3567 因为lyd在讲课,所以有 ...

  5. bzoj 1023: [SHOI2008]cactus仙人掌图

    这道题是我做的第一道仙人掌DP,小小纪念一下…… 仙人掌DP就是环上的点环状DP,树上的点树上DP.就是说,做一遍DFS,DFS的过程中处理出环,环上的点先不DP,先把这些换上的点的后继点都处理出来, ...

  6. BZOJ.1023.[SHOI2008]cactus仙人掌图(DP)

    题目链接 类似求树的直径,可以用(类似)树形DP求每个点其子树(在仙人掌上就是诱导子图)最长链.次长链,用每个点子节点不同子树的 max{最长链}+max{次长链} 更新答案.(不需要存次长链,求解过 ...

  7. bzoj 1023: [SHOI2008]cactus仙人掌图【tarjan+dp+单调队列】

    本来想先求出点双再一个一个处理结果写了很长发现太麻烦 设f[u]为u点向下的最长链 就是再tarjan的过程中,先照常处理,用最长儿子链和次长儿子链更新按ans,然后处理以这个点为根的环,也就是这个点 ...

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

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

  9. 【BZOJ】1023: [SHOI2008]cactus仙人掌图 静态仙人掌(DFS树)

    [题意]给定仙人掌图(每条边至多在一个简单环上),求直径(最长的点对最短路径).n<=50000,m<=10^7. [算法]DFS树处理仙人掌 [题解]参考:仙人掌相关问题的处理方法(未完 ...

随机推荐

  1. Apache服务器笔记

    Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源代码的网页服务器软件,可以在大多数电脑操作系统中运行,由于其跨平台和安全性.被广泛使用,是最流行的Web服务 ...

  2. Vue 使用细节收集

    JSX 中 on 开头的属性名 在用 elementui 中的 el-upload 的时候,他们组件中有一个属性 on-change ,也不知道谁想出来的属性名,太扯淡了,非要 on 开头,我开始的代 ...

  3. libgdx学习记录11——平铺地图TiledMap

    地图对于游戏场景十分重要,很多游戏都需要对地图进行编辑,可使用TileMap进行编辑并生成对应的tmx格式地图文件. 编辑好后,可通过TmxMapLoader来读取地图文件.可通过一个正交相机Otho ...

  4. 使用Redis做分布式

    一 为什么使用 Redis 在项目中使用 Redis,主要考虑两个角度:性能和并发.如果只是为了分布式锁这些其他功能,还有其他中间件 Zookpeer 等代替,并非一定要使用 Redis. 性能: 如 ...

  5. Django的跨域请求

    一 同源策略 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之 ...

  6. SpringBoot整合Mybatis之进门篇

    已经有好些日子没有总结了,不是变懒了,而是我一直在奋力学习springboot的路上,现在也算是完成了第一阶段的学习,今天给各位总结总结. 之前在网上找过不少关于springboot的教程,都是一些比 ...

  7. 阿里云centos 安装禅道

    下载 我的阿里云服务器系统是 centos6.8 64 位,下载的禅道版本是 Linux 64位一键安装包(适用于Linux 64位) 由于阿里云服务器没桌面,所以下载用不了浏览器,可考虑在本地下载后 ...

  8. chrome下的Grunt插件断点调试——基于node-inspector

    之前调试grunt插件时,都是通过人肉打log来调试.不仅效率低,而且会产生一堆无用的代码.于是简单google了下node断点调试的方法,总结了下. 借助node-inspector,我们可以通过C ...

  9. 虚拟机virtualBox安装linux系统 xshell远程连接linux

    虚拟机virtualBox安装linux系统 xshell远程连接linux 虚拟机概念: 通过软件, 使用虚拟化技术虚拟出电脑的硬件环境, 充当真实的电脑使用. 常见的虚拟软件: virtualBo ...

  10. Substrings (C++ find函数应用)

    Description You are given a number of case-sensitive strings of alphabetic characters, find the larg ...