2791: [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

HINT

Source

【分析】

  一开始以为是无向边ORZ。。

  其实有向边只要改一点点东西。

  那个x>=y是用来省掉SPJ的,不是题目要求

  无向边的话,首先是一个基环森林,很明显是求最短路径然后除以二。

  有向边的话,很多路径是固定的,

  首先不是一个联通块的一定无法到达,是一个联通块的一定能到达(也许你觉得有向边不一定可以,但事实上是可以的,因为每个点只有一条出边的特殊性质)

  这种特殊性质告诉我们:

  环一定是通的,就是从环上任意一点走环一定能走回自己。

  基环树下面的点的连边一定是向上的(考虑一个点只有一条出边,而环上的根的出边已经贡献给环了)

  所以如果是同一棵树,那么求LCA,答案是唯一的。

  如果不是,那么环上面也只有两种走法,两个答案比较一下即可。

  【其实一开始看错题之后觉得边有向很难搞,其实知道性质就很简单了】

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 500010 int mymax(int x,int y) {return x>y?x:y;}
int mymin(int x,int y) {return x<y?x:y;}
int myabs(int x) {return x>?x:-x;} struct node
{
int x,y,next,o;
bool p;
}t[Maxn*];int len=;
int first[Maxn]; void ins(int x,int y)
{
t[++len].x=x;t[len].y=y;
t[len].next=first[x];first[x]=len;
t[len].p=;
if(len%==) t[len].o=len-;
else t[len].o=len+;
} int fa[Maxn],r1[Maxn],r2[Maxn];
int ffa(int x)
{
if(x!=fa[x]) fa[x]=ffa(fa[x]);
return fa[x];
} int dis[Maxn];
bool onc[Maxn];
int dfs0(int x,int ff,int rr)
{
dis[x]=dis[ff]+;
if(x==rr) {onc[x]=;return ;}
for(int i=first[x];i;i=t[i].next) if(t[i].y!=ff)
{
int y=t[i].y,z=dfs0(y,x,rr);
if(z!=) {t[i].p=t[t[i].o].p=;onc[x]=;return z+;}
}
return ;
} int tp[Maxn],son[Maxn],sm[Maxn];
int dep[Maxn],siz[Maxn],fd[Maxn];
void dfs1(int x,int ff)
{
sm[x]=;son[x]=;fd[x]=ff;
for(int i=first[x];i;i=t[i].next) if(t[i].p&&t[i].y!=ff)
{
int y=t[i].y;
dis[y]=dis[x];
dep[y]=dep[x]+;
dfs1(y,x);
sm[x]+=sm[y];
if(son[x]==||sm[son[x]]<sm[y]) son[x]=y;
}
} void dfs2(int x,int ff,int tpp)
{
tp[x]=tpp;
if(son[x]) dfs2(son[x],x,tpp);
for(int i=first[x];i;i=t[i].next) if(t[i].y!=ff&&t[i].y!=son[x]&&t[i].p)
{
dfs2(t[i].y,x,t[i].y);
}
} void ffind(int x,int y)
{
int xx=x,yy=y;
while(tp[x]!=tp[y])
{
if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
x=fd[tp[x]];
}
if(dep[x]>dep[y]) swap(x,y);
// return dep[xx]+dep[yy]-2*dep[x];
printf("%d %d\n",dep[xx]-dep[x],dep[yy]-dep[x]);
} int main()
{
int n,q;
scanf("%d%d",&n,&q);
memset(first,,sizeof(first));
memset(r1,,sizeof(r1));
memset(onc,,sizeof(onc));
for(int i=;i<=n;i++) fa[i]=i;
for(int i=;i<=n;i++)
{
int x;
scanf("%d",&x);
if(ffa(x)==ffa(i))
{
r1[ffa(x)]=x;r2[ffa(x)]=i;
}
else
{
if(r1[ffa(x)]!=) r1[ffa(i)]=r1[ffa(x)],r2[ffa(i)]=r2[ffa(x)];
fa[ffa(x)]=ffa(i);
ins(x,i);ins(i,x);
}
}
for(int i=;i<=n;i++) if(ffa(i)==i)
{
dis[r1[i]]=;
siz[i]=dfs0(r1[i],,r2[i]);
}
for(int i=;i<=n;i++) if(onc[i])
{
dep[i]=;
dfs1(i,);
dfs2(i,,i);
}
for(int i=;i<=q;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(ffa(x)!=ffa(y)) {printf("-1 -1\n");continue;}
int sum;
if(dis[x]!=dis[y])
{
sum=mymin(siz[ffa(x)]-myabs(dis[x]-dis[y]),myabs(dis[x]-dis[y]));
int x1,y1,x2,y2;
if(dis[x]<dis[y])
{
x1=dep[x]+dis[y]-dis[x];y1=dep[y];
x2=dep[x];y2=dep[y]+siz[ffa(x)]-(dis[y]-dis[x]);
}
else
{
x1=dep[x];y1=dep[y]+dis[x]-dis[y];
x2=dep[x]+siz[ffa(x)]-(dis[x]-dis[y]);y2=dep[y];
}
if(mymax(x1,y1)<mymax(x2,y2)) printf("%d %d\n",x1,y1);
else if(mymax(x1,y1)>mymax(x2,y2)) printf("%d %d\n",x2,y2);
else
{
if(mymin(x1,y1)<mymin(x2,y2)) printf("%d %d\n",x1,y1);
else if(mymin(x1,y1)>mymin(x2,y2)) printf("%d %d\n",x2,y2);
else if(x1>=y1) printf("%d %d\n",x1,y1);
else printf("%d %d\n",x2,y2);
}
}
else ffind(x,y);
}
return ;
}

2017-02-15 22:07:35

【BZOJ 2791】 2791: [Poi2012]Rendezvous (环套树、树链剖分LCA)的更多相关文章

  1. 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)

    题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...

  2. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  3. CodeForces 916E Jamie and Tree(树链剖分+LCA)

    To your surprise, Jamie is the final boss! Ehehehe. Jamie has given you a tree with n vertices, numb ...

  4. NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分

    原文链接https://www.cnblogs.com/zhouzhendong/p/9275606.html 题目传送门 - 洛谷P1600 题目传送门 - LOJ#2359 题目传送门 - Vij ...

  5. POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)

    题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...

  6. HDU5266 LCA 树链剖分LCA 线段树

    HDU5266 LCA Description 给一棵 n 个点的树,Q 个询问 [L,R] : 求点 L , 点 L+1 , 点 L+2 -- 点 R 的 LCA. Input 多组数据. The ...

  7. [luogu4886] 快递员(点分治,树链剖分,lca)

    dwq推的火题啊. 这题应该不算是点分治,但是用的点分治的思想. 每次找重心,算出每一对询问的答案找到答案最大值,考虑移动答案点,使得最大值减小. 由于这些点一定不能在u的两颗不同的子树里,否则你怎么 ...

  8. cogs 186. [USACO Oct08] 牧场旅行 树链剖分 LCA

    186. [USACO Oct08] 牧场旅行 ★★☆   输入文件:pwalk.in   输出文件:pwalk.out   逐字节对比时间限制:1 s   内存限制:128 MB n个被自然地编号为 ...

  9. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

随机推荐

  1. Mantis 从Windows 迁移到Linux上

    1. 导出windows manits的mysql数据库文件, 在cmd运行:mysqldump -uroot -p3edc$RFV bugtracker > C:/mantis.sql; 2. ...

  2. 20155335俞昆《java程序设计》第十周总结

    学号 2016-2017-2 <Java程序设计>第十周学习总结 ## 事实上网络编程,我们可以简单的理解为两台计算机相互通讯数据而已,对于程序员而言,掌握一种编程接口并使用一种编程模型相 ...

  3. 基本控件文档-UIKit结构图---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址  UIKit结构图 //转载请注明出处--本文永久链接:http://www.cnbl ...

  4. 【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)

    题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r ...

  5. Android Studio注意事项

    http://www.android-studio.org/ 解决方法: 在 Android Studio 安装目录 bin/idea.properties 文件最后追加一句 1 disable.an ...

  6. JSP九大内置对象,七大动作,三大指令

    JSP之九大内置对象 隐藏对象入门探索 Servlet 和JSP中输出数据都需要使用out对象.Servlet 中的out对象是通过getWriter()方法获取的.而JSP中没有定义out对象却可以 ...

  7. C++学习之路(七):以const,enum,inline替换#define

    这篇博文主要是编程中的一些问题和技巧.如题目所示,这些关键字的作用不再进行描述.直接描述功能和实例代码. 首先,在头文件中对类进行定义,是不会为类分配内存空间的,在这一点上类定义可以和普通变量类型的声 ...

  8. 【快速玩转Source Filmmaker】用黑科技做出自己的OC和想要的模型

    [快速玩转Source Filmmaker]用黑科技做出自己的OC和想要的模型https://tieba.baidu.com/p/4154097168

  9. Win7蓝屏代码0X0000007B可能是SATA mode问题

    Win7蓝屏代码0X0000007B可能是硬盘模式的问题,我进入BIOS把SATA的mode从Enhanced改为Compatible(及IDE兼容模式)结果系统可以顺利启动没有问题.       从 ...

  10. vue做购物车

    写一点废话,昨天敲代码找bug,找了好久都没找到,后来一哥们找到他说,找代码的bug就像男女朋友吵架,女问男你错了没,男说错啦,女再问错哪了,男傻眼了不知道错哪.在找代码的过程中一直知道我错啦就是找不 ...