约会 Rendezvous:基环树

提炼:tarjan判环,dfs建树,倍增lca,预处理环两点间距离
我犯的错误:
1.基环树不只有一棵,可以有很多
2.自环不能将其忽略,(对于我的算法)应该将其特殊考虑在算法内
3.代码一定要简洁有力,不能让自己调都恶心
Code
数组含义:
que[N]队列,in_que[N]tarjan判是否入队,dfn[N],low[N],bel[N]点属于的集合
ver[N]根节点的集合编号,to[N],nxt[N],head[N],f[N][20]倍增lca,d[N]深度,bel_rt[N]点属于的树的根
extra[N],Ex[N]特判自环专用,vector<int>vec[N]tarjan点集合
#include<cstdio>
#include<vector>
const int L=<<|;
char buffer[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
using namespace std;
const int N=5e5+;
int n,k,num_tarjan,num_bian,num_huan,top,
que[N],in_que[N],dfn[N],low[N],bel[N],ver[N],to[N],nxt[N],head[N],f[N][],d[N],bel_rt[N],extra[N],Ex[N];
vector<int>vec[N];
int read(){
int x=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x;
}
void add(int x,int y){if(x==y)extra[++extra[]]=x;
to[++num_bian]=y,nxt[num_bian]=head[x],head[x]=num_bian;
}
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a>b?b:a;}
void tarjan(int x){
dfn[x]=low[x]=++num_tarjan;
que[++top]=x;in_que[x]=;
for(int i=head[x],y;i;i=nxt[i])
if(!dfn[y=to[i]])tarjan(y),low[x]=min(low[x],low[y]);
else if(in_que[y])low[x]=min(low[x],dfn[y]);
if(dfn[x]==low[x]){
num_huan++;
int y;
do{
y=que[top--];
in_que[y]=;
vec[num_huan].push_back(y);
bel[y]=num_huan;
}while(y!=x);
if((int)vec[num_huan].size()>)Ex[++Ex[]]=num_huan;
}
}
void dfs(int x,int depth,int root){
bel_rt[x]=root;
d[x]=depth;
for(int i=head[x],y;i;i=nxt[i]){
if(bel[root]!=bel[y=to[i]]&&!d[y=to[i]]){
f[y][]=x;
for(int j=;j<=;++j)f[y][j]=f[f[y][j-]][j-];
dfs(y,depth+,root);
}
}
}
int get(int x,int y){
if(d[x]<d[y])swap(x,y);
for(int i=;i>=;--i)if(d[f[x][i]]>=d[y])x=f[x][i];
if(x==y)return y;
for(int i=;i>=;--i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[y][];
}
int main(){
n=read(),k=read();
for(int i=;i<=n;++i)add(read(),i);
for(int i=;i<=n;++i)if(!dfn[i])tarjan(i);
for(int hua=;hua<=Ex[];++hua){int huan=Ex[hua];
for(int i=;i<(int)vec[huan].size();++i){
dfs(vec[huan][i],,vec[huan][i]);
ver[vec[huan][i]]=i+;
}
}
for(int i=;i<=extra[];++i)
if(!d[extra[i]]){
dfs(extra[i],,extra[i]);
ver[extra[i]]=;
}
for(int i=,x,y;i<=k;++i){
x=read(),y=read();
if(bel[bel_rt[x]]!=bel[bel_rt[y]])
printf("-1 -1\n");
else if(bel_rt[x]==bel_rt[y]){
int lca=get(x,y);
printf("%d %d\n",d[x]-d[lca],d[y]-d[lca]);
}
else{
int ai=d[x]-,bi=d[y]-,huan_dis=(int)vec[bel[bel_rt[x]]].size();
int len_b=ver[bel_rt[x]]-ver[bel_rt[y]],len_a;
if(len_b<)len_a=-*len_b,len_b=huan_dis-len_a;
else len_a=huan_dis-len_b;
int Ma=max(ai+len_a,bi),Mb=max(ai,bi+len_b),ma=min(ai+len_a,bi),mb=min(ai,bi+len_b);
//条件一
if(Ma<Mb)
printf("%d %d\n",ai+len_a,bi);
else if(Ma>Mb)
printf("%d %d\n",ai,bi+len_b);
else{
//条件二
if(ma<mb)
printf("%d %d\n",ai+len_a,bi);
else if(ma>mb)
printf("%d %d\n",ai,bi+len_b);
else{
//条件三
if(ai+len_a>=bi)
printf("%d %d\n",ai+len_a,bi);
else
printf("-1 -1\n");
}
}
} }
return ;
}
约会 Rendezvous:基环树的更多相关文章
- 「POI2012」约会 Rendezvous
#2691. 「POI2012」约会 Rendezvous 这题我简直不想说什么了,什么素质,卡常数…… “每个顶点有且仅有一条出边”,所以是一道基环树的题,首先tarjan缩点,在缩完点后的图上求a ...
- Solution -「基环树」做题记录
写的大多只是思路,比较简单的细节和证明过程就不放了,有需者自取. 基环树简介 简单说一说基环树吧.由名字扩展可得这是一类以环为基础的树(当然显然它不是树. 通常的表现形式是一棵树再加一条非树边,把图画 ...
- 【BZOJ1791】【IOI2008】【基环树】island(status第一速度)
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MB Submit: 908 Solved: 159 [Su ...
- 『Island 基环树直径』
Island(IOI 2008) Description 你准备浏览一个公园,该公园由 N 个岛屿组成,当地管理部门从每个岛屿 i 出发向另外一个岛屿建了一座长度为 L_i 的桥,不过桥是可以双向行走 ...
- 【BZOJ4883】 [Lydsy1705月赛]棋盘上的守卫(最小生成树,基环树)
传送门 BZOJ Solution 考虑一下如果把行,列当成点,那么显然这个东西就是一个基环树对吧. 直接按照\(Kruscal\)那样子搞就好了. 代码实现 代码戳这里
- [Codeforces235D]Graph Game——概率与期望+基环树+容斥
题目链接: Codeforces235D 题目大意:给出一棵基环树,并给出如下点分治过程,求点数总遍历次数的期望. 点分治过程: 1.遍历当前联通块内所有点 2.随机选择联通块内一个点删除掉 3.对新 ...
- 洛谷AT2046 Namori(思维,基环树,树形DP)
洛谷题目传送门 神仙思维题还是要写点东西才好. 树 每次操作把相邻且同色的点反色,直接这样思考会发现状态有很强的后效性,没办法考虑转移. 因为树是二分图,所以我们转化模型:在树的奇数层的所有点上都有一 ...
- bzoj1791[IOI2008]Island岛屿(基环树+DP)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791 题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和.n< ...
- bzoj1040 基环树森林dp
https://www.lydsy.com/JudgeOnline/problem.php?id=1040 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社 ...
随机推荐
- VMware or VirtualBox+centos7 安装教程
一.准备工作:1.首次安装虚拟机时,需要的准备工作:打开intel的虚拟技术服务(否则安装centos系统时会报错).重启电脑,显示log时进入BIOS服务(不同电脑进入BIOS方式不同,一般是进入l ...
- 创建的项目如果没有src/main/resources文件夹,如何解决?
这是刚创建的一个maven项目,由此可以看见,项目并没有存放配置文件的src/main/resources文件夹? 解决方案: (1)选中项目,右键单击,如图所示选择:Build Path --> ...
- 阶段3 2.Spring_09.JdbcTemplate的基本使用_5 JdbcTemplate在spring的ioc中使用
resources下新建File文件 bean.xml 配置jdbcTemplate 注入DataSource 新建测试方法 复制demo1改个名字叫做demo2 编写Insert的方法
- 阶段3 2.Spring_07.银行转账案例_4 编写事务管理工具类并分析连接和线程解绑
事务管理工具类 首先需要有connection.并且是当前线程上的connection.声明connectionUtils.提供set方法等着spring来注入 有异常需要放在事务里面 close关闭 ...
- 阶段3 2.Spring_03.Spring的 IOC 和 DI_12 注入集合数据
再复制一份,改名3 常用的注入方式,这里选择set saveAccount方法输出所有的对象 map需要导包 配置xml 集合类型的值配置方式 在property标签里面再写标签 这里选择array. ...
- 阶段3 2.Spring_03.Spring的 IOC 和 DI_7 spring中bean的细节之作用范围
bean的作用范围调整. 我们的bean通常情况下都是一个单例的模式 Spring是否也知道这些都是单例 构造函数只走了一次.也就是spring这个对象默认情况就是单例的 scope属性 定义bean ...
- VirtualBox-5.2.8-121009-Win,虚拟机指令ifconfig不显示ip解决方法
- 【HANA系列】SAP HANA的ini文件存储路径
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA的ini文件存储 ...
- swagger生成文档初步使用
在大部分情况下,公司都会要求提供详细的接口文档,对于开发来说,文档有时候在赶进度的情况下,也是一件头疼的事.而swagger的自动生成文档功能,就可以帮助我们减少工作量,对于文档的修改也可以在代码中随 ...
- Hbase的几个关键问题(转自log.csdn.net/javastart/article/details/43772575)
什么是HBase?何时用HBase?与Hive.Pig的区别?HBase的结构为何HBase速度很快?HBase常用的操作有哪些?HBase的一些配置和监控 什么是HBase? HBase,是Hado ...