BZOJ2791: [Poi2012]Rendezvous
来源:互联网 发布:linux oracle服务很卡 编辑:程序博客网 时间:2024/06/05 23:56
题目大意:有n个点,每个点有一条出边,再给出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。
2,3,4条件是搞笑的,没有spj,然后就得手动弄出一组定义的解
首先这个图可以看成一堆环,环上每个节点有一个有向的树指向它(大小可能为0)
然后求x,y的话可以分三种情况讨论
1.a,b不在一个联通块上, 则无解
2.a,b在同一个环的同一个节点的子树下,那就是都走到LCA
3.那肯定是两个点都走到环上,然后其中一个向另一个移动,这种情况只需要算出两个解然后根据他给的比较规则来选一个更优的
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define N 500010using namespace std;int a[N];bool vis[N],zai[N],inc[N];int s[N],t;int fa[N][21],bel[N],num[N],tree[N],d[N];int tot[N],cnt;void dfs(int x){vis[x]=true;t++;s[t]=x;zai[x]=true;if(vis[a[x]]){if(!zai[a[x]]) bel[x]=bel[a[x]],fa[x][0]=a[x],d[x]=d[a[x]]+1,tree[x]=tree[a[x]];else{cnt++;while(s[t]!=a[x]){inc[s[t]]=true;t--;}inc[s[t]]=true;tree[x]=x;bel[x]=cnt;tot[cnt]=1;num[x]=1;}zai[x]=false;return;}dfs(a[x]);if(inc[x]){tree[x]=x;bel[x]=cnt;tot[cnt]++;num[x]=tot[cnt];}else{d[x]=d[a[x]]+1;tree[x]=tree[a[x]];bel[x]=bel[a[x]];fa[x][0]=a[x];}zai[x]=false;}int LCA(int x,int y){int i=20;if(d[x]<d[y]) swap(x,y);while(d[x]>d[y]){if(d[x]-d[y]>=(1<<i)) x=fa[x][i];i--;}if(x==y) return x;i=20;while(fa[x][0]!=fa[y][0]){if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];i--;}return fa[x][0];}int main(){int n,q;scanf("%d%d",&n,&q);int i,j,x,y,z,ans1,ans2,cur1,cur2;for(i=1;i<=n;i++)scanf("%d",&a[i]);for(i=1;i<=n;i++)if(!vis[i]) dfs(i);for(j=1;j<=20;j++)for(i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];while(q--){scanf("%d%d",&x,&y);if(bel[x]!=bel[y]) printf("-1 -1\n");else if(tree[x]==tree[y]){z=LCA(x,y);printf("%d %d\n",d[x]-d[z],d[y]-d[z]);}else{int tmp1=tree[x],tmp2=tree[y];ans1=d[x]+num[tmp1]-num[tmp2]+(num[tmp1]>=num[tmp2]?0:tot[bel[x]]);ans2=d[y];cur1=d[x];cur2=d[y]+num[tmp2]-num[tmp1]+(num[tmp2]>=num[tmp1]?0:tot[bel[x]]);if(max(ans1,ans2)!=max(cur1,cur2)){if(max(ans1,ans2)>max(cur1,cur2))ans1=cur1,ans2=cur2;}else if(min(ans1,ans2)!=min(cur1,cur2)){if(min(ans1,ans2)>min(cur1,cur2))ans1=cur1,ans2=cur2;}else if(ans1<ans2)swap(ans1,ans2);printf("%d %d\n",ans1,ans2);}}}
0 0
- BZOJ2791: [Poi2012]Rendezvous
- BZOJ2791/POI2012 Rendezvous
- BZOJ2791: [Poi2012]Rendezvous
- [BZOJ 2791]POI2012 Rendezvous
- BZOJ 2791 Poi2012 Rendezvous 倍增LCA
- bzoj 2791 [Poi2012]Rendezvous 倍增lca 基环树
- TIBCO Rendezvous 概念
- Loadrunner集合点Rendezvous知识
- Loadrunner集合点Rendezvous知识
- RVD (Rendezvous daemon)
- Loadrunner集合点Rendezvous知识
- Loadrunner集合点Rendezvous知识
- Loadrunner集合点Rendezvous知识
- Loadrunner:集合点(Rendezvous)
- POI2012题解
- [Poi2012]Festival
- TIBCO Rendezvous — 技术介绍
- TIBCO Rendezvous — 技术介绍
- 异常org.xmlpull.v1.XmlPullParserException
- 浅谈爬虫
- C#控制台 console.writeline输出变量
- 8张图让你轻轻松松理解Java的各种特性
- HDOJ 2588 GCD
- BZOJ2791: [Poi2012]Rendezvous
- 在有Textfield的页面,键盘弹出效果
- Interoperability Notes EBS 12.0 and 12.1 with Database 11gR2 (11.2.0.4)
- PostgreSQL的SQL语句中的双引号引发的问题
- mysql进阶:复制表结构、表数据技巧
- unity3d对象添加了碰撞体以后OnMouseDown事件
- shell 中while read语句总结
- 371. Sum of Two Integers
- 【学习笔记】GDAL对图像的基本操作(未完成)