[POI2012] 约会 Rendezvous
作者:互联网
约会 Rendezvous
题目描述
给定一个有 n 个顶点的有向图,每个顶点有且仅有一条出边。每次询问给出两个顶点 ai和 bi,求满足以下条件的 xi和yi:
- 从顶点 ai沿出边走 xi步与从顶点 bi沿出边走 yi步到达的顶点相同。
- max(xi,yi)最小。
- 满足以上条件的情况下 min(xi,yi) 最小。
- 如果以上条件没有给出一个唯一的解,则还需要满足 xi≥yi.
如果不存在这样的 xi和 yi,则 xi=yi=−1.
输入格式
第一行两个正整数 n 和 k(1≤n≤500 000,1≤k≤500),表示顶点数和询问个数。
接下来一行 n 个正整数,第 i 个数表示 i 号顶点出边指向的顶点。
接下来 k 行表示询问,每行两个整数 ai和 bi.
输出格式
对每组询问输出两个整数 xi和 yi.
样例
样例输入
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% 的数据,n≤2000,k≤2000
对于 100% 的数据,1≤n≤500 000,1≤k≤500 000.
题解
先用tarjan缩点,然后这个图就变成了一棵树。
1.如果两个点不在一棵树上,xi=yi=-1。
2.在一棵树上,对于这棵树求lca即可。因为每个节点只能连接其他的1个节点,所以对于每一棵树,有且仅有1个环。
最后如果他们的lca是个环的话,可以先预处理出每个节点在根的那个环中连接的位置的编号,最后减的话要分两种情况。
最后要卡一个常,来个fread和快读快输。
#include<iostream> #include<cstring> #include<cstdio> #define Reg register #define Maxn 500050 using namespace std; const int L = 1 << 20 | 1; char buffer[L], *S, *TT; #define getchar() ((S == TT && (TT = (S = buffer) + fread(buffer, 1, L, stdin), S == TT)) ? EOF : *S++) int n,st,k,tot,tpp,sum; int root[Maxn],vap[Maxn],rotsum[Maxn]; int fic[Maxn],fir[Maxn],vis[Maxn]; int stack[Maxn],dfn[Maxn],dep[Maxn],low[Maxn]; int pre[Maxn],gen[Maxn],tre[Maxn]; int pos[Maxn],poj[Maxn],tom[Maxn]; int fat[Maxn][25],len1[Maxn],len2[Maxn]; struct Tu {int st,ed,next;} lian[Maxn],liab[Maxn]; inline int max(Reg int x,Reg int y) {return x>y?x:y;} inline int min(Reg int x,Reg int y) {return x<y?x:y;} inline int read() { Reg int x=0; Reg char c=getchar(); Reg bool flag=0; while(c<'0'||c>'9') {if(c=='-') flag=1; c=getchar();} while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+(c^48); c=getchar();} if(flag) x=-x; return x; } inline void print(Reg int x) { if(x<0) {putchar('-'); x=-x;} if(x>9) print(x/10); putchar(x%10+48); return; } inline void add(Reg int x,Reg int y) { lian[++tot].st=x; lian[tot].ed=y; lian[tot].next=fir[x]; fir[x]=tot; return; } inline void app(Reg int x,Reg int y) { liab[++tpp].st=x; liab[tpp].ed=y; liab[tpp].next=fic[x]; fic[x]=tpp; return; } inline void tarjan(Reg int x) { dfn[x]=low[x]=++sum; stack[++stack[0]]=x; vis[x]=1; if(!dfn[pre[x]]) { tarjan(pre[x]); low[x]=min(low[x],low[pre[x]]); } else if(vis[pre[x]]) low[x]=min(low[x],dfn[pre[x]]); if(low[x]==dfn[x]) { tre[++tre[0]]=0; while(stack[stack[0]]!=x) { ++tre[tre[0]]; vis[stack[stack[0]]]=0; pos[stack[stack[0]]]=tre[0]; --stack[0]; } vis[stack[stack[0]]]=0; pos[stack[stack[0]]]=tre[0]; --stack[0]; } return; } inline void dfs(Reg int x,Reg int root) { gen[x]=root; vis[x]=1; for(Reg int i=fir[x];i;i=lian[i].next) { if(!vis[lian[i].ed]) { fat[lian[i].ed][0]=x; for(Reg int j=1;j<=18;++j) fat[lian[i].ed][j]=fat[fat[lian[i].ed][j-1]][j-1]; dep[lian[i].ed]=dep[x]+1; dfs(lian[i].ed,root); } } return; } inline int lca(Reg int x,Reg int y) { if(dep[x]<dep[y]) swap(x,y); if(x==y) return x; if(dep[x]!=dep[y]) { for(Reg int i=18;i>=0;--i) if(dep[fat[x][i]]>dep[y]) x=fat[x][i]; if(x==y) return x; x=fat[x][0]; } if(x==y) return x; for(Reg int i=18;i>=0;--i) { if(fat[x][i]!=fat[y][i]) { x=fat[x][i]; y=fat[y][i]; } } if(x==y) return x; return fat[x][0]; } inline void dfp(Reg int x,Reg int root) { vis[x]=1,poj[x]=root; for(Reg int i=fic[x];i;i=liab[i].next) if(!vis[liab[i].ed]) dfp(liab[i].ed,root); return; } int main() { n=read(); k=read(); for(Reg int i=1;i<=n;++i) {pre[i]=read(); app(pre[i],i);} for(Reg int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); for(Reg int i=1;i<=n;++i) { if(pos[i]!=pos[pre[i]]) add(pos[pre[i]],pos[i]); else if(!vap[pos[i]]) vap[pos[i]]=1,root[++root[0]]=pos[i]; } for(Reg int i=1;i<=n;++i) if(vap[pos[i]]) vis[i]=1,poj[i]=i,++rotsum[pos[i]],tom[++tom[0]]=i; for(Reg int i=1;i<=tom[0];++i) dfp(tom[i],tom[i]); for(Reg int i=1;i<=n;++i) { if(vap[pos[i]]) { st=i; vap[pos[i]]=0; for(Reg int j=1;j<=rotsum[pos[i]];++j) { if(!len1[st]) len1[st]=j; else len2[st]=j; st=pre[st]; } } } memset(vis,0,sizeof(vis)); if(!root[0]) root[++root[0]]=1; for(Reg int i=1;i<=root[0];++i) {dep[root[i]]=1; dfs(root[i],root[i]);} Reg int l1,l2,ans,lp1,lp2,lc1,lc2,p; for(Reg int i=1,x,y;i<=k;++i) { x=read(); y=read(); if(gen[pos[x]]!=gen[pos[y]]) {print(-1); putchar(' '); print(-1); putchar('\n');} else { p=lca(pos[x],pos[y]); if(p==gen[pos[x]]) { l1=poj[x],l2=poj[y]; if(l1==l2) {print(dep[pos[x]]-1); putchar(' '); print(dep[pos[y]]-1); putchar('\n');} else { if(len1[l1]<len1[l2]) ans=len1[l2]-len1[l1]; else ans=len1[l2]+rotsum[pos[l2]]-len1[l1]; lp1=dep[pos[x]]-1+ans,lp2=dep[pos[y]]-1; lc1=dep[pos[x]]-1,lc2=dep[pos[y]]-1+rotsum[gen[pos[x]]]-ans; if(max(lp1,lp2)!=max(lc1,lc2)) { if(max(lp1,lp2)<max(lc1,lc2)) {print(lp1); putchar(' '); print(lp2); putchar('\n');} else {print(lc1); putchar(' '); print(lc2); putchar('\n'); } } else if(min(lp1,lp2)!=min(lc1,lc2)) { if(min(lp1,lp2)<min(lc1,lc2)) {print(lp1); putchar(' '); print(lp2); putchar('\n');} else {print(lc1); putchar(' '); print(lc2); putchar('\n');} } else { if(lp1>=lp2) {print(lp1); putchar(' '); print(lp2); putchar('\n');} else {print(lc1); putchar(' '); print(lc2); putchar('\n');} } } } else {print(dep[pos[x]]-dep[p]); putchar(' '); print(dep[pos[y]]-dep[p]); putchar('\n');} } } return 0; }View Code
标签:return,vis,POI2012,约会,fat,Reg,int,Rendezvous,stack 来源: https://www.cnblogs.com/Milk-Feng/p/11186922.html