HDU 4297--One and One Story(LCA&並查集)
阿新 • • 發佈:2017-11-18
font lead esp accepted != test case set mini air
You, as a member of the FFF Inquisition,
2 are fed up with such game since you believe that to make things
fair, you should not keep providing guidance information while risking remaining
forever alone 3 . So you decided to write a program working out
guidance for these sweet small lovers on behalf of you. ( Another reason is, you
have to help K couples, which would make you somewhat overwhelmed.
)
Fortunately, you are to handle not the Flash game above, but a simplified
version: In the game, a maze consists of some rooms connected with one-way
hallways. For each room, there is exactly one outgoing hallway here, and it
would lead directly to some room (not necessarily a different one). The boy and
girl are trapped in (not necessarily different) rooms. In each round of the
games, both of them could choose to stay in the current room or walk to the room
to which the unique outgoing hallway leads. Note that boy and girl could act
independently of each other. Your goal is to come to the reunion between
them.
Your program should determine a pair of numbers (A,B) for each couple
of boy and girl, where A represents number of hallway the boy walked through, B
the girl, that could lead reunion between them. First, your program should
minimize max(A,B). If there are several solutions, you should then guarantee
that min(A,B) is minimized subject to above. If, satisfying above conditions,
there are still multiple solutions, girl should walk less, that is you should
then keep A >= B subject to conditions above.
In case they could not reunion, just let A = B = -1. Input There‘re several test cases.
In each test case, in the first line there are two positive integers N and K (1 <= N <= 500000; 1 <= K <= 500000) denoting the number of rooms and number of couples. Rooms a numbered from 1 to N.
The second line contains n positive integers: the ith integer denotes the number of room to which the hallway going out of room i leads.
The following K lines are queries of several couples. Each query consists of two positive integers in a single line denoting the numbers of rooms where the lovers currently are: first the boy, then the girl.
Please process until EOF (End Of File). Output For each test case you should output exactly K lines, one line per query. Each line consists two integers separated by a space: the integer A and B for this couple.
See samples for detailed information. 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 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 2 3 1 2 2 2 0 1 -1 -1
One and One Story
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others)
Total Submission(s): 1049 Accepted Submission(s):
459
In case they could not reunion, just let A = B = -1. Input There‘re several test cases.
In each test case, in the first line there are two positive integers N and K (1 <= N <= 500000; 1 <= K <= 500000) denoting the number of rooms and number of couples. Rooms a numbered from 1 to N.
The second line contains n positive integers: the ith integer denotes the number of room to which the hallway going out of room i leads.
The following K lines are queries of several couples. Each query consists of two positive integers in a single line denoting the numbers of rooms where the lovers currently are: first the boy, then the girl.
Please process until EOF (End Of File). Output For each test case you should output exactly K lines, one line per query. Each line consists two integers separated by a space: the integer A and B for this couple.
See samples for detailed information. 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 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 2 3 1 2 2 2 0 1 -1 -1
題目鏈接:
http://acm.hdu.edu.cn/showproblem.php?pid=4297
Solution
畫圖發現,實際上這個有向圖是一個森林。
首先-1的情況可以用並查集判掉。。
剩下的每一個分離的有向圖都可以看做一顆以一個環為根的樹。。
然後分兩種情況討論:
1. 兩個節點在根的同一顆子樹中,那麽直接LCA
2. 其余情況,肯定要兩個點都先走到環上,然後判斷一下就好了。。。
代碼
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> #define LL long long #define N 500050 using namespace std; inline int Read_(){ int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int n,k,cnt=0,tot=0; int fa[N],hed[N],dep[N],cir[N],rt[N],g[N],num[N],len[N]; int F[N][22]; bool vis[N]; struct edge{ int r,nxt; }e[N]; void insert_(int u,int v){ e[++cnt].r=v;e[cnt].nxt=hed[u];hed[u]=cnt; } int find_(int x){ return fa[x]==x?x:fa[x]=find_(fa[x]); } void dfs(int x){ for(int i=1;i<=20;i++) F[x][i]=F[F[x][i-1]][i-1]; for(int i=hed[x];i;i=e[i].nxt) if(!vis[e[i].r]){ dep[e[i].r]=dep[x]+1; rt[e[i].r]=rt[x]; F[e[i].r][0]=x; vis[e[i].r]=1; dfs(e[i].r); } return; } int lca_(int x,int y){ if(dep[x]<dep[y]) swap(x,y); for(int i=0;(1<<i)<=(dep[x]-dep[y]);i++) if( (1<<i)&(dep[x]-dep[y]) ) x=F[x][i]; if(x==y) return x; for(int i=20;i>=0;i--) if(F[x][i]!=F[y][i]){ x=F[x][i];y=F[y][i]; } return F[x][0]; } int main(){ int u,v,w; while(scanf("%d%d",&n,&k)!=EOF){ cnt=0;tot=0; memset(hed,0,sizeof(hed)); memset(vis,0,sizeof(vis)); memset(F,0,sizeof(F)); memset(num,0,sizeof(num)); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=n;i++){ g[i]=Read_();insert_(g[i],i); u=find_(i);v=find_(g[i]); if(u!=v) fa[u]=v; else cir[++tot]=i; } for(int i=1;i<=tot;i++){ int js=1; u=cir[i];dep[u]=0;rt[u]=u;vis[u]=1;num[u]=js;u=g[u]; while(u!=cir[i]){ js++;dep[u]=0;rt[u]=u;vis[u]=1;num[u]=js;u=g[u]; } len[find_(u)]=js; dfs(u);u=g[u]; while(u!=cir[i]){ dfs(u);u=g[u]; } } for(int i=1;i<=k;i++){ u=Read_();v=Read_(); if(find_(u)!=find_(v)){ printf("-1 -1\n"); continue; } if(rt[u]==rt[v]){ w=lca_(u,v); printf("%d %d\n",dep[u]-dep[w],dep[v]-dep[w]); continue; } int ansu,ansv,ansU,ansV; if(num[rt[u]]<num[rt[v]]){ ansu=dep[u]+num[rt[v]]-num[rt[u]]; ansv=dep[v]; ansU=dep[u]; ansV=dep[v]+len[find_(v)]-num[rt[v]]+num[rt[u]]; if(max(ansu,ansv)<max(ansU,ansV)){ printf("%d %d\n",ansu,ansv);continue; } if(max(ansu,ansv)>max(ansU,ansV)){ printf("%d %d\n",ansU,ansV);continue; } if(min(ansu,ansv)<min(ansU,ansV)){ printf("%d %d\n",ansu,ansv);continue; } if(min(ansu,ansv)>min(ansU,ansV)){ printf("%d %d\n",ansU,ansV);continue; } if(ansv<ansV){ printf("%d %d\n",ansu,ansv);continue; } else{ printf("%d %d\n",ansU,ansV);continue; } } else { ansu=dep[u]; ansv=dep[v]+num[rt[u]]-num[rt[v]]; ansU=dep[u]+len[find_(u)]-num[rt[u]]+num[rt[v]]; ansV=dep[v]; if(max(ansu,ansv)<max(ansU,ansV)){ printf("%d %d\n",ansu,ansv);continue; } if(max(ansu,ansv)>max(ansU,ansV)){ printf("%d %d\n",ansU,ansV);continue; } if(min(ansu,ansv)<min(ansU,ansV)){ printf("%d %d\n",ansu,ansv);continue; } if(min(ansu,ansv)>min(ansU,ansV)){ printf("%d %d\n",ansU,ansV);continue; } if(ansv<ansV){ printf("%d %d\n",ansu,ansv);continue; } else{ printf("%d %d\n",ansU,ansV);continue; } } } } return 0; }
This passage is made by Iscream-2001.
HDU 4297--One and One Story(LCA&並查集)