题目描述

给定一个n个顶点的有向图,每个顶点有且仅有一条出边。

对于顶点i,记它的出边为(i, a[i])。

再给出q组询问,每组询问由两个顶点a、b组成,要求输出满足下面条件的x、y:

  1. 从顶点a沿着出边走x步和从顶点b沿着出边走y步后到达的顶点相同。

  2. 在满足条件1的情况下max(x,y)最小。

  3. 在满足条件1和2的情况下min(x,y)最小。

  4. 在满足条件1、2和3的情况下x>=y。如果不存在满足条件1的x、y,输出-1 -1。

输入格式

第一行两个正整数n和q (n,q<=500,000)。

第二行n个正整数a[1],a[2],...,a[n] (a[i]<=n)。

下面q行,每行两个正整数a,b (a,b<=n),表示一组询问。

输出格式

输出q行,每行两个整数。


第一句话就明显地点明了这是一道基环树的题。并且还是一颗内向基环树。

我们考虑每对x,y的情况:

1.x,y不在一棵基环树上。那么输出-1即可。

2.x,y在同一棵子树上。那么答案就是树上距离,用lca求解即可。

3.x,y在同一棵基环树上,但不在同一棵子树上。由于是有向图,我们可以枚举x走过环到y的距离和y走过环到x的距离,根据题目输出答案即可。

具体流程:

1.首先预处理出环。

2.预处理出树上倍增的fa数组和每个点所在的子树、基环树编号,并且准备好要使用的距离的信息。

对于每个询问,在线回答即可。

时间复杂度为O(N+Q) ~ O((N+Q)logN)

*很容易写爆的基环树的题。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define maxn 500010
#define maxm 500010
using namespace std;struct graph{struct edge{int to,next;edge(){}edge(const int &_to,const int &_next){ to=_to,next=_next; }}e[maxn<<1];int head[maxn],k;inline void init(){ memset(head,-1,sizeof head); }inline void add(const int &u,const int &v){ e[k]=edge(v,head[u]),head[u]=k++; }
}a,b;int id[maxn],stack[maxn],top,col[maxn],cnt,size[maxn];
int fa[maxn][20],root[maxn],dep[maxn];
bool inloop[maxn],vis[maxn],instack[maxn];
int n,m,maxdep;inline int read(){register int x(0),f(1); register char c(getchar());while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f;
}void dfs_getloop(int u){stack[++top]=u,instack[u]=vis[u]=true;for(register int i=a.head[u];~i;i=a.e[i].next){int v=a.e[i].to;if(!vis[v]) dfs_getloop(v);else if(instack[v]){int w,t=top; cnt++;do{ w=stack[t--],instack[w]=false,inloop[w]=true,col[w]=cnt,id[w]=++size[cnt]; }while(w!=v);}}instack[u]=false,top--;
}
void dfs_getfa(int u,int rt){root[u]=rt,col[u]=col[rt];for(register int i=b.head[u];~i;i=b.e[i].next){int v=b.e[i].to;if(inloop[v]||root[v]) continue;dep[v]=dep[u]+1,fa[v][0]=u;for(register int i=1;i<=maxdep;i++) fa[v][i]=fa[fa[v][i-1]][i-1];dfs_getfa(v,rt);}
}inline int lca(int u,int v){if(dep[u]>dep[v]) swap(u,v);for(register int i=maxdep;i>=0;i--) if(dep[fa[v][i]]>=dep[u]) v=fa[v][i];if(u==v) return u;for(register int i=maxdep;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];return fa[u][0];
}inline bool cmp(int x1,int y1,int x2,int y2){if(max(x1,y1)!=max(x2,y2)) return max(x1,y1)<max(x2,y2);if(min(x1,y1)!=min(x2,y2)) return min(x1,y1)<min(x2,y2);return x1>=y1;
}int main(){a.init(),b.init();n=read(),m=read();for(register int i=1;i<=n;i++){int v=read();a.add(i,v),b.add(v,i);}maxdep=(int)log(n)/log(2)+1;for(register int i=1;i<=n;i++) if(!vis[i]) dfs_getloop(i);for(register int i=1;i<=n;i++) if(inloop[i]) dfs_getfa(i,i);for(register int i=1;i<=m;i++){int u=read(),v=read();if(col[u]!=col[v]){ puts("-1 -1"); continue; }if(root[u]==root[v]){int w=lca(u,v);printf("%d %d\n",dep[u]-dep[w],dep[v]-dep[w]);}else{int ans1=dep[u],ans2=dep[v];int dis1=(id[root[u]]-id[root[v]]+size[col[u]])%size[col[u]];int dis2=(id[root[v]]-id[root[u]]+size[col[v]])%size[col[v]];if(cmp(ans1+dis1,ans2,ans1,ans2+dis2)) printf("%d %d\n",ans1+dis1,ans2);else printf("%d %d\n",ans1,ans2+dis2);}}return 0;
}

附上我用来调试的代码(太容易写爆了)

    //for(register int i=1;i<=n;i++) if(inloop[i]) printf("%d ",i);puts("");//for(register int i=1;i<=n;i++)  printf("%d ",id[i]);puts("");//for(register int i=1;i<=n;i++) printf("%d ",col[i]);puts("");//for(register int i=1;i<=n;i++) printf("%d ",size[col[i]]);puts("");//for(register int i=1;i<=n;i++) printf("%d ",root[i]);puts("");//for(register int i=1;i<=n;i++) printf("%d ",dep[i]);puts("");//for(register int i=1;i<=n;i++) printf("%d ",inloop[i]);puts("");/*for(register int i=1;i<=n;i++){for(register int j=0;j<=maxdep;j++) printf("%d ",fa[i][j]);puts("");}*///printf("%d\n",maxdep);

转载于:https://www.cnblogs.com/akura/p/10920021.html

[Poi2012]Rendezvous相关推荐

  1. 【BZOJ2791】[Poi2012]Rendezvous 倍增

    [BZOJ2791][Poi2012]Rendezvous Description 给定一个n个顶点的有向图,每个顶点有且仅有一条出边. 对于顶点i,记它的出边为(i, a[i]). 再给出q组询问, ...

  2. Bzoj3060 [Poi2012]Tour de Byteotia

    3060: [Poi2012]Tour de Byteotia Time Limit: 30 Sec  Memory Limit: 256 MB Submit: 251  Solved: 161 De ...

  3. 洛谷 P3539 [POI2012]ROZ-Fibonacci Representation 解题报告

    P3539 [POI2012]ROZ-Fibonacci Representation 题意:给一个数,问最少可以用几个斐波那契数加加减减凑出来 多组数据10 数据范围1e17 第一次瞬间yy出做法, ...

  4. BZOJ 2788[Poi2012]Festival

    题面: 2788: [Poi2012]Festival Time Limit: 30 Sec  Memory Limit: 64 MB Submit: 418  Solved: 190 [Submit ...

  5. 【BZOJ2797】[Poi2012]Squarks 暴力乱搞

    [BZOJ2797][Poi2012]Squarks Description 设有n个互不相同的正整数{X1,X2,...Xn},任取两个Xi,Xj(i≠j),能算出Xi+Xj. 现在所有取法共n*( ...

  6. TIBCO Rendezvous — 技术介绍

      http://blog.csdn.net/tiercel2008/article/details/6799952 TIBCO Rendezvous - 技术介绍 1.1.1.      TIBCO ...

  7. LR中Action,Transaction,Rendezvous,SubmitData的插入顺序请注意

    先说事务,事务(Transaction)    事务(Transaction)是这样一个点,我们为了衡量某个action的性能,需要在action的开始和结束位置插入这样一个范围,这就定义了一个tra ...

  8. bzoj 2803: [Poi2012]Prefixuffix(双Hash)

    2803: [Poi2012]Prefixuffix Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 413  Solved: 167 [Submit] ...

  9. 编码器SRT协议三种模式(listener, caller, rendezvous)简介

    本文镜像:https://www.linkpi.cn/archives/1027 本文链接:https://blog.csdn.net/weixin_45326556/article/details/ ...

最新文章

  1. JavaServer Faces技术
  2. 高等数学在计算机中的应用论文1500字,数学论文1500字-高数应用论文大一高数的应用论文字数1500左右 爱问知识人...
  3. 如何对待新事物_如何利用这个专栏才能更高效地进步?
  4. 低能量社交时代,我们都成了小心翼翼的「舔狗」
  5. Java中值传递和引用传递原理以及区别
  6. windows删除桌面ie_从Windows 8“开始”屏幕启动IE的桌面版本
  7. 52 - 算法 - LeetCode 20 数据结构类 stack
  8. 使用 jQuery 的 Autocomplete 插件实现input输入提示功能 input 输入模糊提示demo
  9. MySQL 常见面试知识点
  10. 《Java从入门到放弃》JavaSE入门篇:面向对象语法二(入门版)
  11. linux下mysql 8.0忘记密码后重置密码
  12. [Flink]Flink实时框架介绍
  13. laravel 模型事件几种用法
  14. MySQL主从同步(四)——M-M架构配置实战
  15. 40. Element getAttribute() 方法
  16. Atitit 初级 中级 高级 软件工程师的区别 非功能性需求 目录 1. 初级 业务功能 1 1.1. 中级 独立完成业务功能 已经非常见api功能 更加广阔 1 2. 高级 非功能性需求
  17. 将图片url转file类型
  18. 计算机机房系统建设,计算机机房系统建设方案(范文).pdf
  19. windows系统常见端口和木马默认使用端口
  20. 麻省理工十亿美元计算机学院,麻省理工学院宣布10亿美元成立新计算机学院 | 芥末堆...

热门文章

  1. 前端实现三角形的四种方法
  2. 高等数学:第五章 定积分(1)概念与性质 中值定理 微积分基本公式
  3. ISO、快门、光圈、曝光
  4. python中的break、continue和pass
  5. 计算机无法识别出硬件,电脑检测不到网卡硬件信息怎么办
  6. 简单的股票行情演示(一) - 实时标的数据
  7. 好嗨呦是谁_抖音好嗨哟原版 《好嗨哟》原唱是谁怎么火起来的
  8. win10输入法不能切换_怎么解决win10系统微软输入法打不出汉字
  9. 玻尔兹曼机、深度信念网络、编码器等生成模型
  10. 十年磨一剑,两万字长文深剖析分享IC验证经验