约会 Rendezvous

内存限制:128 MiB 时间限制:1000 ms 标准输入输出
 

题目描述

给定一个有 nnn 个顶点的有向图,每个顶点有且仅有一条出边。每次询问给出两个顶点 aia_ia​i​​ 和 bib_ib​i​​,求满足以下条件的 xix_ix​i​​ 和 yiy_iy​i​​:

  • 从顶点 aia_ia​i​​ 沿出边走 xix_ix​i​​ 步与从顶点 bib_ib​i​​ 沿出边走 yiy_iy​i​​ 步到达的顶点相同。
  • max(xi,yi)\max(x_i, y_i)max(x​i​​,y​i​​) 最小。
  • 满足以上条件的情况下 min(xi,yi)\min(x_i, y_i)min(x​i​​,y​i​​) 最小。
  • 如果以上条件没有给出一个唯一的解,则还需要满足 xi≥yix_i \ge y_ix​i​​≥y​i​​.

如果不存在这样的 xix_ix​i​​ 和 yiy_iy​i​​,则 xi=yi=−1x_i = y_i = -1x​i​​=y​i​​=−1.

输入格式

第一行两个正整数 nnn 和 kkk(1≤n≤500 000,1≤k≤500 0001 \le n \le 500\ 000,1 \le k \le 500\ 0001≤n≤500 000,1≤k≤500 000),表示顶点数和询问个数。

接下来一行 nnn 个正整数,第 iii 个数表示 iii 号顶点出边指向的顶点。

接下来 kkk 行表示询问,每行两个整数 aia_ia​i​​ 和 bib_ib​i​​.

输出格式

对每组询问输出两个整数 xix_ix​i​​ 和 yiy_iy​i​​.

样例

样例输入

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

样例输出

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

数据范围与提示

对于 40%40\%40% 的数据,n≤2000,k≤2000n \le 2000,k \le 2000n≤2000,k≤2000.

对于 100%100\%100% 的数据,1≤n≤500 000,1≤k≤500 0001 \le n \le 500\ 000,1 \le k \le 500\ 0001≤n≤500 000,1≤k≤500 000.

Q:这题是不是非常简单?

A:毒瘤题。

Q:毒瘤出题人?

A:毒瘤出题人。

Q:是不是比较考验码力,打完想对就能A?

A:毒瘤卡常,你没有一点卡常技巧是过不了的。

Q:我卡卡常就能A了是吗?

A:卡dfs 卡你空间,卡你时间,还特别容易爆栈 你需要特别的姿势!

34个测试点,让你绝望

没有看题解过了的毒瘤题

对于我这个蒟蒻,我调了一天,整整一天,

day1 晚上开始码 没有看题解 大约想了想,好像可以建反边跑lca

然后思考它有什么性质,首先题目里保证了只有一个出边,那么相当与保证了每个图都有一个环

想到可以缩点然后无脑lca 然后又想了想 好像环上比较难处理

day1 晚上码完 得了 38分 稍微改了改 28分

day2 重新理了理思路,想到环上可以预处理,但没想到怎么处理,随手打了个单调队列发现不行

得到了3分的好成绩

#include<bits/stdc++.h>
#define ll long long
#define A 600000
using namespace std;
ll head[A],nxt[A],belong[A],ver[A],tot=0,deep[A],dis[A],t,n,m,dfn[A],sta[A],otp=0,num=0,top=0,low[A],f[A][30],cnt=0,ins[A],sum[A],rt[A],bl[A],zuzong[A],fa[A],bl4[A];
vector <ll> scc[251001];
bool flag[A];
void add(ll x,ll y)
{nxt[++tot]=head[x];ver[tot]=y;head[x]=tot;}
inline ll lca(ll x,ll y)
{if(deep[x]>deep[y])swap(x,y);for(ll i=t;i>=0;i--){if(deep[x]==deep[y]) break;if(deep[x]<=deep[f[y][i]]) y=f[y][i];}if(x==y) return x;for(ll i=t;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0];
}
void dfs(ll x,ll st,ll t)
{deep[x]=st,flag[x]=1;bl4[x]=otp;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(flag[y]) continue;rt[y]=t;dis[y]=dis[x]+1;f[y][0]=x;dfs(y,st+1,t);}return ;
}
ll read()
{ll f=1,x=0;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return f*x;
}
inline void tarjan(ll x)
{dfn[x]=low[x]=++num;sta[++top]=x;ins[x]=1;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(dfn[y]==0){tarjan(y);low[x]=min(low[x],low[y]);}else if(ins[y])low[x]=min(low[x],dfn[y]);}if(dfn[x]==low[x]){++cnt;ll yy=0,cis=0,lu;while(1){yy=sta[top--];ins[yy]=0;cis++;    bl4[yy]=cnt;if(yy==x)break;scc[cnt].push_back(yy);belong[yy]=-1;//printf("将%lld赋成-1\n",yy);
}if(cis>1) scc[cnt].push_back(x),belong[x]=-1;else cnt--;}
}
void tiaotarjan()
{cout<<"***"<<endl;for(ll i=1;i<=cnt;i++){for(ll j=0;j<scc[i].size();j++){cout<<scc[i][j]<<" ";}if(scc[i].size()) cout<<endl;}        cout<<"***"<<endl;
}
void tiaos()
{
}
void work()
{n=read();m=read();t=log(n)/log(2)+2;for(ll i=1;i<=n;i++){ll xx=read();add(xx,i);//建反图跑tarjan缩点+lca
    }for(ll i=1;i<=n;i++)if(!dfn[i])    tarjan(i);top=0;memset(flag,0,sizeof(flag));for(ll i=1;i<=cnt;i++){ll size=scc[i].size();otp++;for(ll ii=0;ii<size;ii++){ll q=scc[i][ii]; for(ll j=head[q];j;j=nxt[j]){ll y=ver[j];if(belong[y]!=-1){rt[y]=q;dfs(y,1,rt[y]);f[y][0]=y;}}}}for(ll j=1;j<=t;j++)for(ll i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];/*for(ll i=1;i<=n;i++){if(belong[i]!=-1){printf("i=%lld rt=%lld deep=%lld\n",i,rt[i],deep[i]);}}*/for(ll i=1;i<=m;i++){    ll xx=read(),yy=read();if(bl4[xx]==bl4[yy]){ll lc=lca(xx,yy);//printf("rtx=%lld rty=%lld\n",rt[xx],rt[yy]);if(rt[xx]==rt[yy]){printf("%lld %lld\n",dis[xx]-dis[lc],dis[yy]-dis[lc]);}if(rt[xx]!=rt[yy]){ll de1=deep[xx],de2=deep[yy];ll now=bl4[rt[xx]];ll size=scc[now].size(),ott=0;bool kais=0;for(ll ii=0;ii<size*2-1;ii++){    if(ii>size){ll j=ii-size;if(!kais&&(scc[now][ii]==rt[xx]||scc[now][ii]==rt[yy])){kais=1;}else if(kais==1){de1<de2?de1++:de2++;if(scc[now][ii]==rt[xx]||scc[now][ii]==rt[yy]){kais=0;break;}}}else{if(!kais&&(scc[now][ii]==rt[xx]||scc[now][ii]==rt[yy])){kais=1;}else if(kais==1){de1<de2?de1++:de2++;if(scc[now][ii]==rt[xx]||scc[now][ii]==rt[yy]){kais=0;break;}}}}printf("%lld %lld\n",de1,de2);}}elseprintf("-1 -1\n");}
}
int main()
{work();}

View Code

和同学讨论这个题发现他们也挺艰难的

day2 下午 然后经过艰难的辨认+艰难的手膜得到以下代码

          ll lx,ly,bl=belong[ances[x]],rootx=ances[x],rooty=ances[y],disx=deep[x]-deep[rootx],disy=deep[y]-deep[rooty],xy,yx;for(ll j=0;j<scc[bl].size();j++){if(scc[bl][j]==rootx) lx=j;if(scc[bl][j]==rooty) ly=j;}if(lx<ly)xy=ly-lx,yx=sz[bl]-(ly-lx);else yx=lx-ly,xy=sz[bl]-(lx-ly);if(max(disx+xy,disy)<max(disx,disy+yx)) printf("%lld %lld\n",disx+xy,disy);else if(max(disx+xy,disy)>max(disx,disy+yx)) printf("%lld %lld\n",disx,disy+yx);else{if(min(disx+xy,disy)<min(disx,disy+yx)) printf("%lld %lld\n",disx+xy,disy);else if(min(disx+xy,disy)>min(disx,disy+yx)) printf("%lld %lld\n",disx,disy+yx);else if(disx+xy>=disy) printf("%lld %lld\n",disx+xy,disy);else printf("%lld %lld\n",disx,disy+yx);}

然后TLE了

得知tarjan一定会被卡死

然后改成了dfs(??????)

终于吧MLE整过了之后,就接着TLE

经过几个小时卡常斗争终于A了

#include<bits/stdc++.h>
#define ll int
#define A 510000
const int L=1<<20|1;
char buffer[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
using namespace std;
ll head[A],nxt[A],belong[A],ver[A],tot=0,deep[A],t,n,m,otp=0,num=0,f[A][22],cnt=0,bl[A],ances[A],last,sz[A],v[A],cixu[A],chushi=0;
inline ll find(ll x)
{if(ances[x]==x) return x;return ances[x]=find(ances[x]);}
inline void add(ll x,ll y)
{nxt[++tot]=head[x];ver[tot]=y;head[x]=tot;}
inline ll lca(ll x,ll y)
{if(deep[x]>deep[y])swap(x,y);ll w;for(w=0;(1<<w)<=deep[y];w++);w--;for(ll i=w;i>=0;i--){if(deep[x]==deep[y]) break;if(deep[x]<=deep[f[y][i]]) y=f[y][i];}if(x==y) return x;for(ll i=t;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0];
}
inline void dfs(ll x,ll pre)
{v[x]=++num;deep[x]=deep[pre]+1;
//    printf("%lld \n",deep[x]);for(ll i=1;(1<<i)<=deep[x];i++)f[x][i]=f[f[x][i-1]][i-1];for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(v[y]>last){cnt++;chushi=0;cixu[x]=++chushi;sz[cnt]++;belong[x]=cnt;ances[x]=x;for(ll i=x;i!=y;i=f[i][0]){cixu[f[i][0]]=++chushi;belong[f[i][0]]=cnt;ances[f[i][0]]=f[i][0];sz[cnt]++;}}else {ances[y]=f[y][0]=x,dfs(y,x);}}
}
inline ll Read(){register ll ret;register char r;while(r=getchar(),r<'0'||r>'9');ret=r-48;while(r=getchar(),r>='0'&&r<='9')ret=ret*10+r-48;return ret;
}
inline void work()
{last=0;n=Read();m=Read();t=log(n)/log(2)+1;for(ll i=1;i<=n;i++){ll xx=Read();add(xx,i);}for(ll i=1;i<=n;i++)if(!v[i]){ances[i]=f[i][0]=i;dfs(i,0);last=num;}for(ll i=1;i<=m;i++){    ll x=Read(),y=Read();if(find(x)!=find(y)&&belong[ances[x]]!=belong[ances[y]]) printf("-1 -1\n");else{if(ances[x]==ances[y]){ll lc=lca(x,y);printf("%d %d\n",deep[x]-deep[lc],deep[y]-deep[lc]);}else{ll lx,ly,bl=belong[ances[x]],disx=deep[x]-deep[ances[x]],disy=deep[y]-deep[ances[y]],xy,yx;lx=cixu[ances[x]];ly=cixu[ances[y]];if(lx<ly)xy=ly-lx,yx=sz[bl]-(ly-lx);else yx=lx-ly,xy=sz[bl]-(lx-ly);if(max(disx+xy,disy)<max(disx,disy+yx)) printf("%d %d\n",disx+xy,disy);else if(max(disx+xy,disy)>max(disx,disy+yx)) printf("%d %d\n",disx,disy+yx);else{if(min(disx+xy,disy)<min(disx,disy+yx)) printf("%d %d\n",disx+xy,disy);else if(min(disx+xy,disy)>min(disx,disy+yx)) printf("%d %d\n",disx,disy+yx);else if(disx+xy>=disy) printf("%d %d\n",disx+xy,disy);else printf("%d %d\n",disx,disy+yx);}}}}
}
main()
{work();}

View Code

具体思路

首先我们会发现图中一定存在环而且仅仅存在一个环,可能有多个可分割的图,每个图都有一个环

我们要建反图,这样我们就可以跑lca了

然后我们模拟就完了,对于同一个图上的有如下情况

一.路径不经过环

lca完了

二.路径经过环

我们发现我们缩点时其实是按照一定顺序缩的,事实上是按照逆边顺序缩的

于是我们维护一个类似于dfn序的东西就完了

只在环上维护dfn序,相减就得到了距离

对于不在一个图上的直接-1 -1

#include<bits/stdc++.h>
#define ll int
#define A 510000
const int L=1<<20|1;
char buffer[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
using namespace std;
ll head[A],nxt[A],belong[A],ver[A],tot=0,deep[A],t,n,m,otp=0,num=0,f[A][22],cnt=0,bl[A],ances[A],last,sz[A],v[A],cixu[A],chushi=0;
inline ll find(ll x)
{if(ances[x]==x) return x;return ances[x]=find(ances[x]);}
inline void add(ll x,ll y)
{nxt[++tot]=head[x];ver[tot]=y;head[x]=tot;}
inline ll lca(ll x,ll y)
{if(deep[x]>deep[y])swap(x,y);ll w;for(w=0;(1<<w)<=deep[y];w++);w--;for(ll i=w;i>=0;i--){if(deep[x]==deep[y]) break;if(deep[x]<=deep[f[y][i]]) y=f[y][i];}if(x==y) return x;for(ll i=t;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0];
}
inline void dfs(ll x,ll pre)
{v[x]=++num;deep[x]=deep[pre]+1;
//    printf("%lld \n",deep[x]);for(ll i=1;(1<<i)<=deep[x];i++)f[x][i]=f[f[x][i-1]][i-1];for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(v[y]>last){cnt++;chushi=0;cixu[x]=++chushi;sz[cnt]++;belong[x]=cnt;ances[x]=x;for(ll i=x;i!=y;i=f[i][0]){cixu[f[i][0]]=++chushi;belong[f[i][0]]=cnt;ances[f[i][0]]=f[i][0];sz[cnt]++;}}else {ances[y]=f[y][0]=x,dfs(y,x);}}
}
inline ll Read(){register ll ret;register char r;while(r=getchar(),r<'0'||r>'9');ret=r-48;while(r=getchar(),r>='0'&&r<='9')ret=ret*10+r-48;return ret;
}
inline void work()
{last=0;n=Read();m=Read();t=log(n)/log(2)+1;for(ll i=1;i<=n;i++){ll xx=Read();add(xx,i);}for(ll i=1;i<=n;i++)if(!v[i]){ances[i]=f[i][0]=i;dfs(i,0);last=num;}for(ll i=1;i<=m;i++){    ll x=Read(),y=Read();if(find(x)!=find(y)&&belong[ances[x]]!=belong[ances[y]]) printf("-1 -1\n");else{if(ances[x]==ances[y]){ll lc=lca(x,y);printf("%d %d\n",deep[x]-deep[lc],deep[y]-deep[lc]);}else{ll lx,ly,bl=belong[ances[x]],disx=deep[x]-deep[ances[x]],disy=deep[y]-deep[ances[y]],xy,yx;lx=cixu[ances[x]];ly=cixu[ances[y]];if(lx<ly)xy=ly-lx,yx=sz[bl]-(ly-lx);else yx=lx-ly,xy=sz[bl]-(lx-ly);if(max(disx+xy,disy)<max(disx,disy+yx)) printf("%d %d\n",disx+xy,disy);else if(max(disx+xy,disy)>max(disx,disy+yx)) printf("%d %d\n",disx,disy+yx);else{if(min(disx+xy,disy)<min(disx,disy+yx)) printf("%d %d\n",disx+xy,disy);else if(min(disx+xy,disy)>min(disx,disy+yx)) printf("%d %d\n",disx,disy+yx);else if(disx+xy>=disy) printf("%d %d\n",disx+xy,disy);else printf("%d %d\n",disx,disy+yx);}}}}
}
main()
{work();}

View Code

转载于:https://www.cnblogs.com/znsbc-13/p/11202343.html

约会Rendezvous相关推荐

  1. 暑期集训日志(Day0~Day5)

    章·五:2019-07-15:明月不谙离恨苦,斜光到晓穿朱户 ·昨日小结: 昨天考试又是爆零边缘,除了难过就剩难过了. T1暴力打崩了只拿了5分. T2没给分时间.最后20分钟打了个残码.没仔细观察数 ...

  2. 男人约会动机大揭秘。

    被人约是好事,但也要眼明心亮,男人约会动机大揭秘. 男人约会动机大揭秘: 1:这是一个有诚意的开始,表明他是早有计划和你约会的.至少,也说明他有相当的社交礼貌. 2:这个男人可能只是一时寂寞了,如果你 ...

  3. 【PAT (Basic Level) 】1014 福尔摩斯的约会 (20 分)

    大侦探福尔摩斯接到一张奇怪的字条: 我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm 大侦探很快就明白了,字条上 ...

  4. VS Code竟然能约会,找对象不看脸,看编程水平

    晓查 发自 凹非寺  量子位 报道 | 公众号 QbitAI VS Code现在居然可以用来谈恋爱了. 为了用最硬核的方式找到男(女)朋友,23岁的程序员Ben Awad在VS Code里打造一个约会 ...

  5. 怎么主动发起话题_约会的时候,多聊这4个话题,女人才会失去抵抗力

    约会就意味着跟女人在足够短的距离配合足够短的时间进行短兵相接,唯有用你的三寸不烂之舌才能够做到不战,照样能够旗开得胜,说服女人就是从内部攻破女人的防线. 一.女人想要的未来在哪里,你就需要跟女人聊到哪 ...

  6. 2021年了,为什么约会软件算法仍然如此糟糕?

    来源:大数据文摘本文约2000字,建议阅读5分钟在爱情中,就像在其他任何事情中一样,幸运偏爱勇敢的人. 疫情期间,约会软件迎来了爆发期. 但随着社会的再次放开,仍然有越来越多的单身人士选择线上软件.根 ...

  7. “新视野”和“最远点”的约会

    NASA 设想的2014 MU69 太空岩石 来源:中国科学报 当新年香槟将陌生人聚在一起时,一种不同的聚会正在外太阳系进行.在距地球近65亿公里的地方,美国宇航局(NASA)"新视野&qu ...

  8. P1516 青蛙的约会 [exgcd]

    P1516 青蛙的约会 题意:在一个长为\(l\)的环上面有两只青蛙,一只出发点为\(x\),一次跳\(m\),另一只出发点为\(y\),一次跳\(n\),求相遇时间. 这个长为\(l\)的环不难想到 ...

  9. OSChina 周一乱弹 —— 还一星期就要和女神约会了

    2019独角兽企业重金招聘Python工程师标准>>> Osc乱弹歌单(2018)请戳(这里) [今日歌曲] @胖达panda :分享Lenka的单曲<The Long Way ...

  10. pb 里面有个report object_【园所新闻】我们与秋天有个“约会” ——记区一实幼尧佳园亲子秋游活动...

    我们与秋天有个"约会" --记区一实幼尧佳园亲子秋游活动 秋天的枝头硕果累累,秋天的树叶色彩缤纷,秋天正张开臂膀等着孩子们,进行一场快乐的"约会".为了这场&q ...

最新文章

  1. 女程序员婚前买房给父母住,婚后要求男程序员一起还房贷!男程序员怀疑婚姻!...
  2. 买走5355.5万张床垫的年轻人,实现“深睡自由”了吗?
  3. [云炬python3玩转机器学习笔记] 1-3课程所使用的主要技术栈
  4. windows查看java进程详细信息的几种方法
  5. Ubuntu下VIM(GVIM)环境配置
  6. php 证书 paypal,php – Paypal访问 – SSL证书:无法获取本地颁发者证书
  7. 利用Swipejs轻松实现手机上的图片手势切换
  8. crontab命令 :Linux下定时执行脚本
  9. 在构造函数中释放对象本身
  10. 毕业工具大全:开题、答辩、格式排版等stata、spss等多种统计软件、绘图软件(附送教学视频)超200G资料
  11. 程序猿必看10本好书推荐
  12. Winrar去广告图文教程
  13. python 转盘 圆形,用python实现一个转盘
  14. 语音识别使用推荐(讯飞、百度、腾讯、云知声等)
  15. 系统模块化备援 服务器,无法登录到 CMM 以进行英特尔® 模块化服务器系统
  16. html中数字输入框,HTML “input number数字”输入控件简介说明
  17. 分布式算法(中科大分布式算法课程笔记)
  18. #边学边记 必修4 高项:对事的管理 第5章 项目成本管理 之 项目成本估算
  19. 解决IDEA 前端返回值乱码问题
  20. Shadow框架接入遇到的一些错误解决

热门文章

  1. Linux在VMware中如何创建网站
  2. python 正则表达式的应用
  3. 好有成就感。。。又编了一个扫雷
  4. 计算机中低级语言和高级语言的区别?
  5. 获取文件夹中所有图片文件
  6. MTK6577手机有哪些 MT6577手机汇总
  7. 七牛云图片服务器搭建,对接
  8. python提取首字符 判断火车票座位_python实战之通过爬虫实现火车票查询
  9. 暂时解决Xmarks无法同步
  10. 【读书】格鲁夫给经理人的第一课-管理杠杆率