[SHOI2008]cactus仙人掌图

Description
如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus)。所谓简单回路就是指在图上不重复经过任何一个顶点的回路。
1.jpg
举例来说,上面的第一个例子是一张仙人图,而第二个不是——注意到它有三条简单回路:(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
9 1 2 3 4 5 6 7 8 3
7 2 9 10 11 12 13 10
5 2 14 9 15 10

Sample Output 1
8

Sample Input 2
10 1
10 1 2 3 4 5 6 7 8 9 10

Sample Output 2
9

HINT
对第一个样例的说明:如图,6号点和12号点的最短路径长度为8,所以这张图的直径为8。
2.jpg
【注意】使用Pascal语言的选手请注意:你的程序在处理大数据的时候可能会出现栈溢出。
如果需要调整栈空间的大小,可以在程序的开头填加一句:{$M 5000000},其中5000000即
指代栈空间的大小,请根据自己的程序选择适当的数值。


首先建立一棵圆方树,记每个环上dfs序最小的点为\(x_i\),则每个环代表的方点向各自所拥有的\(x_i\)连一条边权为1的边,环上其他的圆点向方点连一条边权为圆点到所属\(x_i\)最短距离的边

然后我们求圆方树的直径,显然是需要记录一条最长链\((f[i])\)和次长链\((g[i])\)的。如果当前点是圆点,则直接用\(f[i]+g[i]\)更新答案;如果当前点是方点,则考虑环上所有点(除去每个环内的\(x_i\),因为在圆方树上\(x_i\)是方点的父亲),按照一定顺序,用单调队列维护\(f[i]+f[j]+dis(i,j)\)的最大值即可

单调队列那里显然要破环成链然后倍长……但是我发现我没有倍长也过了……

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){int x=0,f=1; char ch=gc();for (;ch<'0'||ch>'9';ch=gc())   if (ch=='-')    f=-1;for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';return x*f;
}
inline int read(){int x=0,f=1; char ch=getchar();for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<3)+(x<<1)+ch-'0';return x*f;
}
inline void print(int x){if (x<0)    putchar('-'),x=-x;if (x>9)    print(x/10);putchar(x%10+'0');
}
const int N=1e5,M=2e5;
int V[N+10],deep[N+10],dfn[N+10],belong[N+10];
int n,m,Ans,cnt;
vector<int>vec[N+10];
int dis(int x,int y,int pos){if (!x||!y) return 0;if (dfn[x]<dfn[y])  swap(x,y);return min(deep[x]-deep[y],V[pos]-deep[x]+deep[y]);
}
struct S1{int pre[(M<<1)+10],now[M+10],child[(M<<1)+10],val[(M<<1)+10],tot;int f[M+10],g[M+10],fa[M+10];void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}int work(int pos){static int h[(N<<1)+10];int head=1,tail=0,res=0; h[1]=0;//记得清空h[1]for (vector<int>::iterator it=vec[pos].begin();it!=vec[pos].end();it++){if (it==vec[pos].begin())   continue;while (head<=tail&&(dis(h[head],*it,pos)>V[pos]/2||h[head]==*it))   head++;res=max(res,f[*it]+f[h[head]]+dis(h[head],*it,pos));while (head<=tail&&f[h[tail]]<=f[*it])  tail--;h[++tail]=*it;}for (vector<int>::iterator it=vec[pos].begin();it!=vec[pos].end();it++){if (it==vec[pos].begin())   continue;while (head<=tail&&(dis(h[head],*it,pos)>V[pos]/2||h[head]==*it))   head++;res=max(res,f[*it]+f[h[head]]+dis(h[head],*it,pos));while (head<=tail&&f[h[tail]]<=f[*it])  tail--;h[++tail]=*it;}return res;}void dfs(int x){for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){if (son==fa[x]) continue;fa[son]=x,dfs(son);int V=f[son]+val[p];if (f[x]<V) g[x]=f[x],f[x]=V;else    if (g[x]<V) g[x]=V;}if (x<=n)   Ans=max(Ans,f[x]+g[x]);else    Ans=max(Ans,work(x-n));}
}RST;//Round Square Tree
struct S2{int pre[(M<<1)+10],now[N+10],child[(M<<1)+10];int fa[N+10],stack[N+10],low[N+10];int Time,tot,top,num;bool instack[N+10];void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}void insert(int x,int y){join(x,y),join(y,x);}void dfs(int x){dfn[x]=++Time,deep[x]=deep[fa[x]]+1;for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){if (son==fa[x]) continue;if (!dfn[son]){fa[son]=x;dfs(son);}else   if (dfn[son]<dfn[x]){V[++cnt]=deep[x]-deep[son]+1;vec[cnt].push_back(son),RST.insert(cnt+n,son,0);for (int i=x;i!=son;i=fa[i])    vec[cnt].push_back(i),RST.insert(cnt+n,i,dis(i,son,cnt));}}}void tarjan(int x){dfn[x]=low[x]=++Time;instack[stack[++top]=x]=1;for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){if (son==fa[x]) continue;if (!dfn[son])  tarjan(son),low[x]=min(low[x],low[son]);else    if (instack[son])   low[x]=min(low[x],dfn[son]);}if (low[x]==dfn[x]){instack[x]=0,belong[x]=++num;while (stack[top]!=x)   instack[stack[top]]=0,belong[stack[top--]]=num;top--;}}void init(){Time=0;memset(dfn,0,sizeof(dfn));}
}OT;//Original Tree
struct S3{int x,y;void insert(int _x,int _y){x=_x,y=_y;}
}Line[M+10];
int main(){n=read(),m=read();int L_cnt=0;for (int i=1;i<=m;i++){int k=read(),last=read();for (int j=1;j<k;j++){int x=read();OT.insert(last,x);Line[++L_cnt].insert(last,x);last=x;}}OT.dfs(1),OT.init(),OT.tarjan(1);for (int i=1;i<=L_cnt;i++)if (belong[Line[i].x]!=belong[Line[i].y])RST.insert(Line[i].x,Line[i].y,1);RST.dfs(1);printf("%d\n",Ans);return 0;
}

转载于:https://www.cnblogs.com/Wolfycz/p/10284295.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351579.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 导入导出txt文件_Java读取和写入txt文件

1 问题描述对于java的读取和写入txt一直心存疑惑&#xff0c;随着知识的积累&#xff0c;又重新进行学习&#xff0c;对java的文件读写理解更加深刻&#xff0c;在这里将自己的小小经验总结分享给大家。下面是大家了解java流的一个基本框架。2 问题分析在java中&#xff0c;jav…

[国家集训队] tree Ⅱ

bzoj2631&#xff08;权限题。。。&#xff09;:链接 落咕:链接 考察的是LCT维护链上信息。 但是这个题不一样的是又有加法又有乘法。。。&#xff08;有木有想到落咕的模板——线段树2qwq&#xff09; 因为乘法的运算优先度比加法高&#xff0c;所以我们要先做乘法再做加法&am…

C++拷贝构造函数(深拷贝,浅拷贝)

对于普通类型的对象来说&#xff0c;它们之间的复制是很简单的&#xff0c;例如&#xff1a; int a88; int ba; 而类对象与普通对象不同&#xff0c;类对象内部结构一般较为复杂&#xff0c;存在各种成员变量。下面看一个类对象拷贝的简单例子。 #include <iostream>u…

java用for循环修改密码_Java for循环的几种用法分析

J2SE 1.5提供了另一种形式的for循环。借助这种形式的for循环&#xff0c;可以用更简单地方式来遍历数组和Collection等类型的对象。本文介绍使用这种循环的具体方式&#xff0c;说明如何自行定义能被这样遍历的类&#xff0c;并解释和这一机制的一些常见问题。在Java程序中&…

apache camel_Apache Camel入门

apache camel在先前的博文中&#xff0c;我们了解了企业集成模式&#xff08;EIP&#xff09;。 现在&#xff0c;在这篇文章中&#xff0c;我们将研究实现这些模式的Apache Camel框架。 关于骆驼&#xff1a; Apache Camel是一个开放源代码项目&#xff0c;已有将近5年的历史…

C++拷贝构造函数详解

一. 什么是拷贝构造函数 首先对于普通类型的对象来说&#xff0c;它们之间的复制是很简单的&#xff0c;例如&#xff1a; [c-sharp] view plaincopyint a 100; int b a; 而类对象与普通对象不同&#xff0c;类对象内部结构一般较为复杂&#xff0c;存在各种成员变量。 …

mysql经典总结文章_MySQL基础篇(01):经典实用查询案例,总结整理

一、连接查询图解示意图1、建表语句部门和员工关系表&#xff1a;CREATE TABLE tb_dept (id int(11) NOT NULL AUTO_INCREMENT COMMENT 主键ID,deptName varchar(30) DEFAULT NULL COMMENT 部门名称,PRIMARY KEY (id)) ENGINEInnoDB AUTO_INCREMENT6 DEFAULT CHARSETutf8;CREAT…

针对故障场景的血液,汗液和书写自动集成测试

去年冬天&#xff0c;我为仍在工作的客户编写并发布了一项服务。 总体而言&#xff0c;该服务满足了业务需求和性能要求&#xff0c;但是使用该服务的一个团队告诉我&#xff0c;他们定期遇到一个问题&#xff0c;该问题是该服务将返回500个错误&#xff0c;并且在重新启动该服…

java 8 update 11_从Java 8升级到Java 11应该注意的问题

从 Java 8迁移到Java 11比大多数升级更棘手。以下是这个过程的一些注意事项。模块在Java 9中Java引入了历史上最大的变化之一 是模块&#xff0c;但&#xff1a;不必将你自己的代码模块化以后才能升级到Java 11。在大多数情况下&#xff0c;放在类路径classpath上的代码能继续在…

标签树的三种遍历

一、标签树的下行遍历 属性说明.contents子节点的列表&#xff0c;将<tag>所有儿子节点存入列表中&#xff08;只能获取下一级儿子节点&#xff09;.children子节点的迭代类型&#xff0c;与.contents类似&#xff0c;用于循环遍历儿子节点.descendants子孙节点的迭代类型…

Git 使用规范流程

团队开发中&#xff0c;遵循一个合理、清晰的Git使用流程&#xff0c;是非常重要的。 否则&#xff0c;每个人都提交一堆杂乱无章的commit&#xff0c;项目很快就会变得难以协调和维护。 下面是ThoughtBot 的Git使用规范流程。我从中学到了很多&#xff0c;推荐你也这样使用Git…

oracle安装静默

安装环境&#xff1a;centos71、修改主机名 /etc/sysconfig/network#HOSTNAMEoracledb.012、修改ip和对应的主机名 /etc/hosts#10.5.1.190 oracledb.013、关闭Selinux /etc/selinux/config#SELINUXdisabled4、参考官方文档安装依赖的软件包 binutils-2.23.52.0.1-12.el7.x86_64…

[MEGA DEAL] Ultimate Java开发和认证指南(59%折扣)

通过介绍世界上最受欢迎的编程语言之一掌握Java编程概念 嘿&#xff0c;怪胎&#xff0c; 本周&#xff0c;在我们的JCG Deals商店中 &#xff0c;我们提供了一个极端的报价 。 我们提供的《 Ultimate Java Development and Certification Guide 》 仅售20美元&#xff0c;而…

python浅拷贝的说法_Python中List的复制(直接复制、浅拷贝、深拷贝)

直接赋值&#xff1a;如果用 直接赋值&#xff0c;是非拷贝方法。这两个列表是等价的&#xff0c;修改其中任何一个列表都会影响到另一个列表。old [1,[1,2,3],3]new []for i in range(len(old)):new.append(old[i])new[0] 3new[1][0] 3-----------------------Before:[1,…

AliOS-Things Visual studio code helloworld 入门

配置环境的时候别忘了下载&#xff1a;GCC工具链&#xff1a;https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads AliOS Things 完成第一个应用&#xff1a;Hello World 全局掌控 从Git上下载源码用VSCode打开源码&#xff0c;查看源码的目录结构打开Hello…

java 联网_java网络

这个图很形象的展示了OSI的五层架构之间的关系。OSI被称为开放式互联&#xff0c;是国际标准组织制定的网络模型&#xff0c;本来是七层&#xff0c;后来把表现层和会话层加到应用层里面了。那么五层模型中的每一层具体都是干什么的呢&#xff1f;在标准的网络模型中&#xff0…

[小米OJ] 4. 最长连续数列

思路&#xff1a; 时间限制为O(n)&#xff0c;即不能使用先排序后寻找的方法。 这里利用哈希表查询插入复杂度都为O(1)的特性来解&#xff0c;利用一个哈希表来保存每一个数字以及其所在数列的长度。 遍历每一个数字n&#xff1a;查询表中是否存在n-1和n1&#xff0c;若存在&am…

控制反转

控制反转[编辑] 维基百科&#xff0c;自由的百科全书控制反转&#xff08;Inversion of Control&#xff0c;缩写为IoC&#xff09;&#xff0c;是面向对象编程中的一种设计原则&#xff0c;可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入&#xff08;Depe…

使用Mutability Detector对Java数据类的不变性进行单元测试

在我们所有的项目中&#xff0c;我们使用的数据类根据定义包含数据&#xff08;字段&#xff09;&#xff0c;但不包含&#xff08;业务&#xff09;逻辑。 根据最佳编码实践&#xff0c;数据类最好应该是不可变的&#xff0c;因为不可变性意味着线程安全。 这里的主要参考是J…

三种单例模式的C++实现

简介 因为在设计或开发中&#xff0c;肯定会有这么一种情况&#xff0c;一个类只能有一个对象被创建&#xff0c;如果有多个对象的话&#xff0c;可能会导致状态的混乱和不一致。这种情况下&#xff0c;单例模式是最恰当的解决办法。它有很多种实现方式&#xff0c;各自的特性不…