博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ1023:[SHOI2008]仙人掌图——题解
阅读量:7236 次
发布时间:2019-06-29

本文共 2393 字,大约阅读时间需要 7 分钟。

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

15 3
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

8
9

——————————————————————————

看hzwer的博客吧:

(以及虽然我知道怎么做了但是不会单调队列的我决定什么时候会了单调队列什么时候再补题解)

#include
#include
#include
#include
#include
using namespace std;typedef long long ll;const int N=50005;const int M=20000005;inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X;}struct node{ int to; int nxt;}edge[M];int head[N],val[N],num[N],cnt=0;int n,m,low[N],dfn[N],fa[N],t=0;int ans=0,dep[N],f[N],a[N*2];int q[N*2],l,r;bool vis[N];inline void add(int u,int v){ cnt++; edge[cnt].to=v; edge[cnt].nxt=head[u]; head[u]=cnt; return;}void dp(int rt,int u){ int delta=dep[u]-dep[rt]+1; for(int i=u;i!=rt;i=fa[i])a[delta--]=f[i]; a[delta]=f[rt]; delta=dep[u]-dep[rt]+1; for(int i=1;i<=delta;i++)a[i+delta]=a[i]; q[1]=1;l=r=1; for(int i=2;i<=2*delta;i++){ while(l<=r&&i-q[l]>delta/2)l++; ans=max(ans,a[i]+i+a[q[l]]-q[l]); while(l<=r&&a[q[r]]-q[r]<=a[i]-i)r--; q[++r]=i; } for(int i=2;i<=delta;i++){ f[rt]=max(f[rt],a[i]+min(i-1,delta-i+1)); } return;}void tarjan(int u){ dfn[u]=low[u]=++t; for(int i=head[u];i;i=edge[i].nxt){ int v=edge[i].to; if(v==fa[u])continue; if(!dfn[v]){ fa[v]=u; dep[v]=dep[u]+1; tarjan(v); low[u]=min(low[u],low[v]); }else{ low[u]=min(low[u],dfn[v]); } if(dfn[u]

 

转载于:https://www.cnblogs.com/luyouqi233/p/8241274.html

你可能感兴趣的文章
我的友情链接
查看>>
我的友情链接
查看>>
Hive使用ORC格式存储离线表
查看>>
Spring工作原理
查看>>
httpd(2.2&2.4)RPM搭建配置定义详解
查看>>
ubuntu下字体
查看>>
linux压缩格式及安装包管理,screen
查看>>
我的友情链接
查看>>
记录linux下通过对limits的设置来优化系统性能
查看>>
Linux下安装无线网卡
查看>>
apache的commons-fileupload中FileItem类和ServletFileUpload
查看>>
列表嵌套元祖排序
查看>>
jquery自动切换tabs选项卡的具体实现
查看>>
使用MDaemon作垃圾邮件过滤网关攻略
查看>>
python脚本判断一个数是否为素数的几种方法
查看>>
Java学习笔记(39)——Java集合11之Stack
查看>>
office 2010打开word文件提示以安全模式打开
查看>>
Microsoft virtual WiFi Miniport Adapter
查看>>
linux /dev/null 对ssh登录的影响
查看>>
连上***后 自己的电脑用公司网络
查看>>