约会 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国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社 ...
随机推荐
- 第七章 SpringCloud之非声明式RestClient:Feign
study-url:https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/1.4.6.RELEASE/multi/multi ...
- Android 动态申请权限
AndroidManifest.xml(清单文件)添加需要的权限 <uses-permission android:name="android.permission.ACCESS_CO ...
- java 接口default的判断规则
1.前言 jdk1.8中新增加了default关键字,就是在接口中可以增加默认实现. 因为改动接口所有的实现类都要改动,所以增加了default关键字后不需要修改其他类,默认给所有实现类增加了方法. ...
- Kafka集群搭建和配置
Kafka配置优化 https://www.jianshu.com/p/f62099d174d9 1.安装&配置 下载tar包 解压后即可使用 修改配置文件 将server.propertie ...
- python 爬取动态数据
按照:https://dryscrape.readthedocs.io/en/latest/installation.html 安装dryscrape 以下是简单实现 import dryscrape ...
- Centos 6.5 磁盘修复 破解删除root密码
起因:由于存储设备故障.导致虚拟机断开.恢复后虚拟机无法启动,发现报磁盘损坏,需要运行fsck运行 问题解决思路: 1.虚拟机无法启动,所以需要进入系统进行修复 2.root密码是自动修改的.由于虚拟 ...
- 磊哥的密码箱icpc11526
问题 D: 磊哥的密码箱 时间限制: 1 Sec 内存限制: 128 MB提交: 238 解决: 61[提交] [状态] [命题人:admin] 题目描述 磊哥有个密码箱,里面装的都是令磊哥羞羞的 ...
- 关于ElementUI中日期选择器时间选择范围限制
1.组件代码 <el-date-picker v-model="value1" type="date" placeholder="选择日期&qu ...
- linux whoami 显示当前用户的用户名
[root@MongoDB ~]# whoami root
- 使用注解方式搭建SpringMVC
1.以前搭建Spring MVC 框架一般都使用配置文件的方式进行,相对比较繁琐.spring 提供了使用注解方式搭建Spring MVC 框架的方式,方便简洁.使用Spring IOC 作为根容器管 ...