BZOJ2791 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行,每行两个整数。
思路:其实我觉得基环树题就是暴力模拟题……先找环,然后有多种情况,在环上某点的同一子树下,在环上不同子树下,不在同一联通块内,一一处理即可
#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的更多相关文章
- 【BZOJ2791】[Poi2012]Rendezvous 倍增
[BZOJ2791][Poi2012]Rendezvous Description 给定一个n个顶点的有向图,每个顶点有且仅有一条出边.对于顶点i,记它的出边为(i, a[i]).再给出q组询问,每组 ...
- [BZOJ2791][Poi2012]Rendezvous
2791: [Poi2012]Rendezvous Time Limit: 25 Sec Memory Limit: 128 MBSubmit: 95 Solved: 71[Submit][Sta ...
- [BZOJ2791]:[Poi2012]Rendezvous(塔尖+倍增LCA)
题目传送门 题目描述 给定一个有n个顶点的有向图,每个顶点有且仅有一条出边.每次询问给出两个顶点${a}_{i}$和${b}_{i}$,求满足以下条件的${x}_{i}$和${y}_{i}$: ...
- TensorFlow中的通信机制——Rendezvous(二)gRPC传输
背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 本篇是TensorFlow通信机制系列的第二篇文章,主要梳理使用gRPC网络传 ...
- TensorFlow中的通信机制——Rendezvous(一)本地传输
背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 在TensorFlow源码中我们经常能看到一个奇怪的词——Rendezvous ...
- Loadrunner集合点Rendezvous知识
摘自: http://blog.csdn.net/richnaly/article/details/7967364 集合点的意思时等到特定的用户数后再一起执行某个操作,比如一起保存,一起提交(我们通常 ...
- 【BZOJ 2791】 2791: [Poi2012]Rendezvous (环套树、树链剖分LCA)
2791: [Poi2012]Rendezvous Description 给定一个n个顶点的有向图,每个顶点有且仅有一条出边.对于顶点i,记它的出边为(i, a[i]).再给出q组询问,每组询问由两 ...
- 「POI2012」约会 Rendezvous
#2691. 「POI2012」约会 Rendezvous 这题我简直不想说什么了,什么素质,卡常数…… “每个顶点有且仅有一条出边”,所以是一道基环树的题,首先tarjan缩点,在缩完点后的图上求a ...
- 约会Rendezvous
约会 Rendezvous 内存限制:128 MiB 时间限制:1000 ms 标准输入输出 题目描述 给定一个有 nnn 个顶点的有向图,每个顶点有且仅有一条出边.每次询问给出两个顶点 ai ...
随机推荐
- Python简要标准库(1)
sys sys这个模块让你能够访问与Python解释器联系紧密的变量和函数 其中的一些在下表 F argv 命令行参数,包括脚本名称 exit([arg]) 退出当前的程序,可选参数为给定的返回值或者 ...
- Unity编辑器 - DragAndDrop拖拽控件
Unity编辑器 - DragAndDrop拖拽控件 Unity编辑器的拖拽(DragAndDrop)在网上能找到的资料少,自己稍微研究了一下,写了个相对完整的案例,效果如下 代码: object d ...
- WCF:REST + Basic authentification + IIS
近期一个项目中用到Restful WCF提供服务,但是需要验证机制,网上搜刮了一些,都是太复杂.FQ找到了一篇不错的文章分享一下. 原地址连接:http://vgolovchenko.wordpres ...
- HDFS essay 2 - Clarify Name Node / Checkpoint Node/ Backup Node
为什么想用英文写了?我获取知识.技术的大部分途径都是通过英文,所以按照自己的理解用英文写下来也比较容易,另外,很多term都是不能翻译的,如果要持续学习技术和知识,那就不但要习惯去阅读,听,还要写,说 ...
- C struct中的位域 bitfield
C struct中的位域 bitfield 结构体的成员可以限制其位域,每个成员可以使用用比字节还小的取值范围,下面的结构体s1中,四个成员每个成员都是2bit的值(0~3),整个结构体占据的空间依然 ...
- 测试报告M2
1,项目简介我们已经在第一次测试报告中说过,这一次主要说一下场景测试实例 1.1测试人员 测试人员包括团队开发小组成员以及特邀测试用户组. 1) 团队内部测试主要针对网站支持的各功能组件进行一一测试 ...
- LintCode-371.用递归打印数字
用递归打印数字 用递归的方法找到从1到最大的N位整数. 注意事项 用下面这种方式去递归其实很容易: recursion(i) { if i > largest number: return re ...
- <Effective C++>读书摘要--Resource Management<一>
1.除了内存资源以外,Other common resources include file descriptors, mutex locks, fonts and brushes in graphi ...
- MVC4 DropDownList (一) — 使用方法
1.下面代码包含了三种绑定DropDownList的方法 using System; using System.Collections.Generic; using System.Linq; usin ...
- 3ds Max学习日记(七)
第7章讲的是多边形建模,实例略多,有十六个,再加上周日的怠惰感,只做了几个实例. 附上今日的劳动成果: 布料(创建一个平面,转换为可编辑多边形,然后调整顶点,连接一些边,添加网格平滑,转换为可 ...