2791: [Poi2012]Rendezvous

Time Limit: 25 Sec  Memory Limit: 128 MB
Submit: 259  Solved: 160
[Submit][Status][Discuss]

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


HINT

Source

[Submit][Status][Discuss]

HOME
Back


题解

我是很久没有好好写一篇题解了。

首先分析题意,是要沿着出边跳到相同的节点,说明要求的是lca。

然后说一下基环树的套路:

  1. 树上倍增可以照常写,注意使用的条件就行了。
  2. 一遍拓扑排序把环找出来,这时候连通且未标记的肯定都在同一个环内。
  3. 以环上任意节点为起点开始做一个环标号,环长度前缀和,还有环总长。具体可以直接用出边跳。
  4. 把不在环上的点的出边反向用来建树,以环为根处理深度,环根标号

这样询问时的处理套路:

  1. 不在同一连通块内,即环根标号对应节点的环标号不同,那么lca不存在。
  2. 在同一棵树内,即环根标号相同,直接树上lca解决。
  3. 这题我们主要解决的情况——在同一连通块内,但是不在同一棵树内,即环根标号对应节点的环标号相同,但环根标号不同。

    x,y肯定要调到环上,然后分为两种情况,x,y分别跳。用预处理的3解决。

这样询问时间复杂度可以做到\(O(1)\),不过这题我的简便写法是\(O(\log n)\)的。总时间复杂度\(((n+m)\log n)\)

#include<bits/stdc++.h>
#define co const
#define il inline
#define rg register
template<class T>T read(){
rg T data=0,w=1;rg char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>T read(T&x){
return x=read<T>();
}
typedef long long ll;
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second co int N=5e5+1;
int n,m,t,f[N][20],deg[N];
int pos[N],cnt,len[N],s[N];
int d[N],id[N];
vector<int> e[N];
queue<int> q; int lca(int x,int y){
if(d[x]>d[y]) swap(x,y);
for(int i=19;i>=0;--i)
if(d[f[y][i]]>=d[x]) y=f[y][i];
if(x==y) return x;
for(int i=19;i>=0;--i)
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
pii cmp(co pii&a,co pii&b){
if(max(a.x,a.y)<max(b.x,b.y)) return a;
if(max(a.x,a.y)>max(b.x,b.y)) return b;
if(min(a.x,a.y)<min(b.x,b.y)) return a;
if(min(a.x,a.y)>min(b.x,b.y)) return b;
return a.x>=a.y?a:b;
}
int main(){
read(n),read(m);
for(int i=1;i<=n;++i) ++deg[read(f[i][0])];
// prework
t=log(n)/log(2);
for(int i=1;i<=t;++i)
for(int x=1;x<=n;++x) f[x][i]=f[f[x][i-1]][i-1];
// topsort
for(int i=1;i<=n;++i)if(!deg[i]) q.push(i);
while(q.size()){
int x=q.front();q.pop();
if(!--deg[f[x][0]]) q.push(f[x][0]);
}
// circle
for(int i=1;i<=n;++i)if(deg[i]&&!pos[i]){
++cnt;
for(int j=i;!pos[j];j=f[j][0])
pos[j]=cnt,s[j]=++len[cnt];
}
// bfs
for(int i=1;i<=n;++i){
if(pos[i]) id[i]=i,q.push(i);
else e[f[i][0]].push_back(i);
}
while(q.size()){
int x=q.front();q.pop();
for(unsigned i=0;i<e[x].size();++i){
int y=e[x][i];
d[y]=d[x]+1,id[y]=id[x];
q.push(y);
}
}
while(m--){
int x=read<int>(),y=read<int>();
if(pos[id[x]]!=pos[id[y]]) puts("-1 -1");
else if(id[x]==id[y]){
int p=lca(x,y);
printf("%d %d\n",d[x]-d[p],d[y]-d[p]);
}
else{
pii a,b;
int sx=s[id[x]],sy=s[id[y]],now=len[pos[id[x]]];
a.x=d[x]+(sy-sx+now)%now,a.y=d[y];
b.x=d[x],b.y=d[y]+(sx-sy+now)%now;
pii ans=cmp(a,b);
printf("%d %d\n",ans.x,ans.y);
}
}
return 0;
}

LG3533 [POI2012]RAN-Rendezvous的更多相关文章

  1. Solution -「基环树」做题记录

    写的大多只是思路,比较简单的细节和证明过程就不放了,有需者自取. 基环树简介 简单说一说基环树吧.由名字扩展可得这是一类以环为基础的树(当然显然它不是树. 通常的表现形式是一棵树再加一条非树边,把图画 ...

  2. [BZOJ2791][Poi2012]Rendezvous

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

  3. 【BZOJ2791】[Poi2012]Rendezvous 倍增

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

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

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

  5. 「POI2012」约会 Rendezvous

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

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

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

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

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

  8. [Poi2012]Rendezvous

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

  9. POI2012题解

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

随机推荐

  1. Python菜鸟之路:Python基础-Socket基础-1

    预热知识 OSI 七层模型 谈到TCP/IP,就不得不说OSI七层模型,OSI 是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供 ...

  2. OutOfMemoryError: Java heap space和GC overhead limit exceeded在Ant的Build.xml中的通用解决方式

    这个仅仅是一点点经验,总结一下,当中前两个相应第一个Error.后两个相应第二个Error,假设heap space还不够.能够再改大些. <jvmarg value="-Xms512 ...

  3. 搜索ABAP程序代码中的字符串

    标准程序名:RPR_ABAP_SOURCE_SCAN /BEV1/NERM07DOCS

  4. JITWatch工具

    JITWatch,执行程序时监测Java HotSpot JIT编译器如何运作的工具,有助于做JVM的性能优化 wiki: https://github.com/AdoptOpenJDK/jitwat ...

  5. 简单做出HTML5翻页效果文字特效

    之前在网上看到一款比较有新意的HTML5文字特效,文字效果是当鼠标滑过是出现翻开折叠的效果,类似书本翻页.于是我兴致勃勃的点开源码看了一下,发现其实实现也挺简单的,主要利用了CSS3的transfor ...

  6. 【leetcode刷题笔记】Edit Distance

    Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2 ...

  7. 【leetcode刷题笔记】Unique Binary Search Trees II

    Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...

  8. File Space——一个java structs2.0的小栗子(DIY)

    1 概述 File Space系统适用于团体,主要提供的是团队文件分享以及个人文件的存储管理服务.分为个人文件存储管理平台和团队文件共享平台. 个人文件存储平台主要为个人提供相关的文件分类存储服务:该 ...

  9. noVNC

    noNVC基础用法: 1.下载noVNC git clone https://github.com/novnc/noVNC.git 2.编辑qemu.conf配置文件 Vim /etc/libvirt ...

  10. Codeforces 245H Queries for Number of Palindromes:区间dp

    题目链接:http://codeforces.com/problemset/problem/245/H 题意: 给你一个字符串s. 然后有t个询问,每个询问给出x,y,问你区间[x,y]中的回文子串的 ...