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行,每行两个整数。

思路:其实我觉得基环树题就是暴力模拟题……先找环,然后有多种情况,在环上某点的同一子树下,在环上不同子树下,不在同一联通块内,一一处理即可

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + ; int head[N], now;
struct edges{
int to, next, w;
}edge[N<<];
void add(int u, int v, int w){ edge[++now] = {v, head[u], w}; head[u] = now;}
void read(int &x){
int f=;x=;char s=getchar();
while(s<''||s>''){if(s=='-')f=-;s=getchar();}
while(s>=''&&s<=''){x=x*+s-'';s=getchar();}
x*=f;
} int n, q, dfn[N], sz, pre[N], tot, c[N], dict[N], bel[N], fa[N][], dep[N], pos[N];
vector<int> cir[N];
void fcur(int x){
dfn[x] = ++sz; bel[x] = tot;
for(int i = head[x]; i; i = edge[i].next){
int v = edge[i].to;
if(v == pre[x]) continue;
if(dfn[v]){
if(dfn[v] < dfn[x]) continue;
cir[tot].push_back(x); c[x] = tot;
for(; x != v; v = pre[v]){
cir[tot].push_back(v), c[v] = tot;
}
}else pre[v] = x, fcur(v);
}
return ;
} void dfs(int x, int father, int root){
dict[x] = root; fa[x][] = father;
for(int i = head[x]; i; i = edge[i].next){
int v = edge[i].to;
if(v == father || c[v]) continue;
dep[v] = dep[x] + ;
dfs(v, x, root);
}
}
int LCA(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
int k=dep[u]-dep[v];
for(int i=;i<=;i++)
if((<<i)&k) u=fa[u][i];
if(u==v) return u;
for(int i=;i>=;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][];
}
void dfs2(int x, int step){
pos[x] = step;
for(int i = head[x]; i; i = edge[i].next){
int v = edge[i].to;
if(edge[i].w && !pos[v]) dfs2(v, step + );
}
}
int main(){
read(n), read(q);
int x, y;
for(int i = ; i <= n; i++){
read(x);
add(i, x, ), add(x, i, );
}
for(int i = ; i <= n; i++){
if(!dfn[i]){
sz = ; tot++;
fcur(i);
}
}
for(int i = ; i <= tot; i++){
dfs2(cir[i][], );
for(int j = ; j < cir[i].size(); j++){
x = cir[i][j];
dict[x] = x;
dfs(x, x, x);
}
}
for(int j = ; j <= ; j++)
for(int i = ; i <= n; i++)
fa[i][j + ] = fa[fa[i][j]][j];
while(q--){
scanf("%d%d", &x, &y);
if(bel[x] != bel[y]){
puts("-1 -1"); continue;
}else if(dict[x] == dict[y]){
int lca = LCA(x, y);
printf("%d %d\n", dep[x] - dep[lca], dep[y] - dep[lca]);
}else{
int rt1 = dict[x], rt2 = dict[y], siz = cir[bel[x]].size();
int s1 = dep[x] - dep[rt1], s2 = dep[y] - dep[rt2];
int k1, k2;
if(pos[rt1] < pos[rt2]) k1 = pos[rt2] - pos[rt1], k2 = siz - k1;
else k2 = pos[rt1] - pos[rt2], k1 = siz - k2;
int tmp1 = s1 + k1, tmp2 = s2 + k2;
if(max(tmp1, s2) != max(s1, tmp2)){
if(max(tmp1, s2) > max(s1, tmp2)) printf("%d %d\n", s1, tmp2);
else printf("%d %d\n", tmp1, s2);
continue;
}
else if(min(tmp1, s2) != min(s1, tmp2)){
if(min(tmp1, s2) > min(s1, tmp2)) printf("%d %d\n", s1, tmp2);
else printf("%d %d\n", tmp1, s2);
continue;
}
else{
if(tmp1 >= s2) printf("%d %d\n", tmp1, s2);
else printf("%d %d\n", s1, tmp2);
}
}
}
return ;
}

BZOJ2791 Rendezvous的更多相关文章

  1. 【BZOJ2791】[Poi2012]Rendezvous 倍增

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

  2. [BZOJ2791][Poi2012]Rendezvous

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

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

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

  4. TensorFlow中的通信机制——Rendezvous(二)gRPC传输

    背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 本篇是TensorFlow通信机制系列的第二篇文章,主要梳理使用gRPC网络传 ...

  5. TensorFlow中的通信机制——Rendezvous(一)本地传输

    背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 在TensorFlow源码中我们经常能看到一个奇怪的词——Rendezvous ...

  6. Loadrunner集合点Rendezvous知识

    摘自: http://blog.csdn.net/richnaly/article/details/7967364 集合点的意思时等到特定的用户数后再一起执行某个操作,比如一起保存,一起提交(我们通常 ...

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

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

  8. 「POI2012」约会 Rendezvous

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

  9. 约会Rendezvous

    约会 Rendezvous 内存限制:128 MiB 时间限制:1000 ms 标准输入输出     题目描述 给定一个有 nnn 个顶点的有向图,每个顶点有且仅有一条出边.每次询问给出两个顶点 ai ...

随机推荐

  1. mysql数据库基本操作命令

    1.登录命令 mysql -u root -p "password" 2.列出所有数据库 show databases; 3.使用数据库 use db_name 4.列出数据库中所 ...

  2. C++11 type_traits 之is_convertible源码分析

    请看源码: struct __sfinae_types { typedef char __one; typedef ]; } __two; }; template<typename _From, ...

  3. ionic typescript--验证码发送倒计时功能

    1.新建页面 ionic g page forget   2.mode.html文件 <ion-item> <ion-input clearInput [(ngModel)]='co ...

  4. 最全的Markdown语法

    目录 Markdown语法 多级标题 引用与注释 插入代码 行内代码 代码段 图片 超链接 行内超链接 参数式超链接 字体 表格 分割线 多级列表 无序列表 有序列表 多选框 LaTeX公式 行内La ...

  5. AC 自动机——多模式串匹配

    网站上的敏感词过滤是怎么实现的呢? 实际上,这些功能最基本的原理就是字符串匹配算法,也就是通过维护一个敏感词的字典,当用户输入一段文字内容后,通过字符串匹配算法来检查用户输入的内容是否包含敏感词. B ...

  6. Linux error:No space left on device

    一台Oracle数据库服务器在关机重启后,Oracle监听无法启动,提示错误 Linux error:no space left on device 提示可知:问题是出在磁盘空间不足 但是初步查看分区 ...

  7. BZOJ 3166 HEOI2013 ALO 可持久化trie+st表

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3166(洛谷上也有) 题意概述: 给出一个序列,对于一个区间,其权值为区间中的次大值亦或区 ...

  8. codeforces 295C Greg and Friends(BFS+DP)

    One day Greg and his friends were walking in the forest. Overall there were n people walking, includ ...

  9. 使用HTML5制作loading图

    昨天发了一篇使用HTML5 canvas写的时钟的文章,今天发一篇关于使用HTML5制作loading图的文章. <!DOCTYPE html> <html> <head ...

  10. Thunder团队贡献分分配规则

    规则1:基础分,拿出总分的40%进行均分. 规则2:参与会议者,每人次加0.5分. 规则3:积极贡献者,通过团队投票,半数及以上同意,每次加0.5分. 规则4:根据项目完成情况,核实每个人的工作量,投 ...