【BZOJ2791】[Poi2012]Rendezvous

Description

给定一个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。

Input

第一行两个正整数n和q (n,q<=500,000)。
第二行n个正整数a[1],a[2],...,a[n] (a[i]<=n)。
下面q行,每行两个正整数a,b (a,b<=n),表示一组询问。

Output

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

Sample Input

12 5
4 3 5 5 1 1 12 12 9 9 7 1
7 2
8 11
1 2
9 10
10 5

Sample Output

2 3
1 2
2 2
0 1
-1 -1

题解:由于给出的是个基环树森林,所以我们考虑如下几种情况。

1.最终不会走到一个环上,-1。
2.还没走到环上就相遇,那么我们用倍增,当成树上LCA来处理即可。
3.走到环上才相遇,那么相遇点一定是两人刚走到环上时的两个点中的一个,判一下即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int maxn=500010;
int n,m,sum,cnt;
int r[20][maxn],to[maxn],next[maxn],head[maxn],Log[maxn],bel[maxn],pos[maxn],len[maxn],toc[maxn],d[maxn];
queue<int> q;
vector<int> v[maxn];
inline void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
inline int lca(int a,int b)
{
if(d[a]<d[b]) swap(a,b);
for(int i=Log[d[a]-d[b]];i>=0;i--) if(d[r[i][a]]>=d[b]) a=r[i][a];
if(a==b) return a;
for(int i=Log[d[a]];i>=0;i--) if(r[i][a]!=r[i][b]) a=r[i][a],b=r[i][b];
return r[0][a];
}
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;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
int main()
{
n=rd(),m=rd();
memset(head,-1,sizeof(head));
int i,j,u,a,b,x,y,x1,y1,x2,y2;
for(i=1;i<=n;i++) r[0][i]=rd(),d[r[0][i]]++;
for(i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
for(j=1;(1<<j)<=n;j++) for(i=1;i<=n;i++) r[j][i]=r[j-1][r[j-1][i]];
for(i=1;i<=n;i++) if(!d[i]) q.push(i);
while(!q.empty())
{
u=q.front(),q.pop();
d[r[0][u]]--;
if(!d[r[0][u]]) q.push(r[0][u]);
}
for(i=1;i<=n;i++) if(d[i]&&!bel[i])
for(sum++,j=i;!bel[j];j=r[0][j]) pos[j]=++len[sum],bel[j]=sum;
for(i=1;i<=n;i++)
{
if(bel[i]) d[i]=0,toc[i]=i,q.push(i);
else add(r[0][i],i);
}
while(!q.empty())
{
u=q.front(),q.pop();
for(i=head[u];i!=-1;i=next[i]) d[to[i]]=d[u]+1,toc[to[i]]=toc[u],q.push(to[i]);
}
for(i=1;i<=m;i++)
{
a=rd(),b=rd();
if(bel[toc[a]]!=bel[toc[b]]) printf("-1 -1\n");
else if(toc[a]==toc[b])
{
x=lca(a,b);
printf("%d %d\n",d[a]-d[x],d[b]-d[x]);
}
else
{
x=d[a],a=toc[a],y=d[b],b=toc[b];
x1=x+(pos[b]-pos[a]+len[bel[a]])%len[bel[a]],y1=y;
x2=x,y2=y+(pos[a]-pos[b]+len[bel[b]])%len[bel[b]];
if(cmp(x1,y1,x2,y2)) printf("%d %d\n",x1,y1);
else printf("%d %d\n",x2,y2);
}
}
return 0;
}//12 5 4 3 5 5 1 1 12 12 9 9 7 1 7 2 8 11 1 2 9 10 10 5

【BZOJ2791】[Poi2012]Rendezvous 倍增的更多相关文章

  1. [BZOJ2791][Poi2012]Rendezvous

    2791: [Poi2012]Rendezvous Time Limit: 25 Sec  Memory Limit: 128 MBSubmit: 95  Solved: 71[Submit][Sta ...

  2. [BZOJ2791]:[Poi2012]Rendezvous(塔尖+倍增LCA)

    题目传送门 题目描述 给定一个有n个顶点的有向图,每个顶点有且仅有一条出边.每次询问给出两个顶点${a}_{i}$和${b}_{i}$​​,求满足以下条件的${x}_{i}$和${y}_{i}$:   ...

  3. 【BZOJ 2791】 2791: [Poi2012]Rendezvous (环套树、树链剖分LCA)

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

  4. [Poi2012]Rendezvous

    题目描述 给定一个n个顶点的有向图,每个顶点有且仅有一条出边. 对于顶点i,记它的出边为(i, a[i]). 再给出q组询问,每组询问由两个顶点a.b组成,要求输出满足下面条件的x.y: 从顶点a沿着 ...

  5. bzoj 2791 [Poi2012]Rendezvous 基环森林

    题目大意 给定一个n个顶点的有向图,每个顶点有且仅有一条出边. 对于顶点i,记它的出边为(i, a[i]). 再给出q组询问,每组询问由两个顶点a.b组成,要求输出满足下面条件的x.y: 从顶点a沿着 ...

  6. POI2012题解

    POI2012题解 这次的完整的\(17\)道题哟. [BZOJ2788][Poi2012]Festival 很显然可以差分约束建图.这里问的是变量最多有多少种不同的取值. 我们知道,在同一个强连通分 ...

  7. LG3533 [POI2012]RAN-Rendezvous

    2791: [Poi2012]Rendezvous Time Limit: 25 Sec  Memory Limit: 128 MBSubmit: 259  Solved: 160[Submit][S ...

  8. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  9. 「POI2012」约会 Rendezvous

    #2691. 「POI2012」约会 Rendezvous 这题我简直不想说什么了,什么素质,卡常数…… “每个顶点有且仅有一条出边”,所以是一道基环树的题,首先tarjan缩点,在缩完点后的图上求a ...

随机推荐

  1. LeetCode 155 Min Stack(最小栈)

    翻译 设计支持push.pop.top和在常量时间内检索最小元素的栈. push(x) -- 推送元素X进栈 pop() -- 移除栈顶元素 top() -- 得到栈顶元素 getMin() -- 检 ...

  2. assert 函数

    assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义: #include <assert.h> void assert( i ...

  3. DevExpress中chartControl中实现统计图功能

    public partial class Form1 : DevExpress.XtraEditors.XtraForm { public Form1() { InitializeComponent( ...

  4. Hystrix入门执行过程

    netflix-hystrix团队开发了hystrix-javanica,使用流行的java注解以及函数式编程,来替代hystrix枯燥的编程方法. 其主要是HystrixCommand注解的使用. ...

  5. php图片采集后按原路径保存图片

    php图片采集后按原路径保存图片. 代码: <?php $domain ='http://www.jbxue.com'; $url = '/newskin/images/v4/logo.jpg' ...

  6. atitit.新增编辑功能 跟orm的实现 attilax p31

    atitit.新增编辑功能 跟orm的实现 attilax p31 1. 流程的实现 1 2. view的实现(dwr) 1 3. 获取表结构 1 4. grep filt req params 2 ...

  7. wget镜像网站并且下载到指定目录 2012-06-20 19:40:56

    wget镜像网站并且下载到指定目录 2012-06-20 19:40:56 分类: Python/Ruby wget -r -p -np -k -P /tmp/ap http://www.exampl ...

  8. 检查是否是移动端(Mobile)、ipad、iphone、微信、QQ等

    <script type="text/javascript"> //判断访问终端 var browser={ versions:function(){ var u = ...

  9. 如何利用wireshark对TCP消息进行分析

    原文:https://www.cnblogs.com/studyofadeerlet/p/7485298.html 如何利用wireshark对TCP消息进行分析   (1) 几个概念介绍 1 seq ...

  10. 16c554 的头文件

    //------------------------------------------------------------------------------ #ifndef AT16C554H # ...