日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【BZOJ2791】[Poi2012]Rendezvous 倍增

發(fā)布時(shí)間:2023/12/10 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【BZOJ2791】[Poi2012]Rendezvous 倍增 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【BZOJ2791】[Poi2012]Rendezvous

Description

給定一個(gè)n個(gè)頂點(diǎn)的有向圖,每個(gè)頂點(diǎn)有且僅有一條出邊。
對(duì)于頂點(diǎn)i,記它的出邊為(i, a[i])。
再給出q組詢問,每組詢問由兩個(gè)頂點(diǎn)a、b組成,要求輸出滿足下面條件的x、y:
1. 從頂點(diǎn)a沿著出邊走x步和從頂點(diǎn)b沿著出邊走y步后到達(dá)的頂點(diǎn)相同。
2. 在滿足條件1的情況下max(x,y)最小。
3. 在滿足條件1和2的情況下min(x,y)最小。
4. 在滿足條件1、2和3的情況下x>=y。
如果不存在滿足條件1的x、y,輸出-1 -1。

Input

第一行兩個(gè)正整數(shù)n和q (n,q<=500,000)。
第二行n個(gè)正整數(shù)a[1],a[2],...,a[n] (a[i]<=n)。
下面q行,每行兩個(gè)正整數(shù)a,b (a,b<=n),表示一組詢問。

Output

輸出q行,每行兩個(gè)整數(shù)。

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

題解:由于給出的是個(gè)基環(huán)樹森林,所以我們考慮如下幾種情況。

1.最終不會(huì)走到一個(gè)環(huán)上,-1。
2.還沒走到環(huán)上就相遇,那么我們用倍增,當(dāng)成樹上LCA來處理即可。
3.走到環(huán)上才相遇,那么相遇點(diǎn)一定是兩人剛走到環(huán)上時(shí)的兩個(gè)點(diǎn)中的一個(gè),判一下即可。

#include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <vector> using namespace std; const int maxn=500010; int n,m,sum,cnt; int r[20][maxn],to[maxn],next[maxn],head[maxn],Log[maxn],bel[maxn],pos[maxn],len[maxn],toc[maxn],d[maxn]; queue<int> q; vector<int> v[maxn]; inline void add(int a,int b) {to[cnt]=b,next[cnt]=head[a],head[a]=cnt++; } inline int lca(int a,int b) {if(d[a]<d[b]) swap(a,b);for(int i=Log[d[a]-d[b]];i>=0;i--) if(d[r[i][a]]>=d[b]) a=r[i][a];if(a==b) return a;for(int i=Log[d[a]];i>=0;i--) if(r[i][a]!=r[i][b]) a=r[i][a],b=r[i][b];return r[0][a]; } inline bool cmp(int x1,int y1,int x2,int y2) {if(max(x1,y1)!=max(x2,y2)) return max(x1,y1)<max(x2,y2);if(min(x1,y1)!=min(x2,y2)) return min(x1,y1)<min(x2,y2);return x1>=y1; } inline int rd() {int ret=0,f=1; char gc=getchar();while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();return ret*f; } int main() {n=rd(),m=rd();memset(head,-1,sizeof(head));int i,j,u,a,b,x,y,x1,y1,x2,y2;for(i=1;i<=n;i++) r[0][i]=rd(),d[r[0][i]]++;for(i=2;i<=n;i++) Log[i]=Log[i>>1]+1;for(j=1;(1<<j)<=n;j++) for(i=1;i<=n;i++) r[j][i]=r[j-1][r[j-1][i]];for(i=1;i<=n;i++) if(!d[i]) q.push(i);while(!q.empty()){u=q.front(),q.pop();d[r[0][u]]--;if(!d[r[0][u]]) q.push(r[0][u]);}for(i=1;i<=n;i++) if(d[i]&&!bel[i])for(sum++,j=i;!bel[j];j=r[0][j]) pos[j]=++len[sum],bel[j]=sum;for(i=1;i<=n;i++){if(bel[i]) d[i]=0,toc[i]=i,q.push(i);else add(r[0][i],i);}while(!q.empty()){u=q.front(),q.pop();for(i=head[u];i!=-1;i=next[i]) d[to[i]]=d[u]+1,toc[to[i]]=toc[u],q.push(to[i]);}for(i=1;i<=m;i++){a=rd(),b=rd();if(bel[toc[a]]!=bel[toc[b]]) printf("-1 -1\n");else if(toc[a]==toc[b]){x=lca(a,b);printf("%d %d\n",d[a]-d[x],d[b]-d[x]);}else{x=d[a],a=toc[a],y=d[b],b=toc[b];x1=x+(pos[b]-pos[a]+len[bel[a]])%len[bel[a]],y1=y;x2=x,y2=y+(pos[a]-pos[b]+len[bel[b]])%len[bel[b]];if(cmp(x1,y1,x2,y2)) printf("%d %d\n",x1,y1);else printf("%d %d\n",x2,y2);}}return 0; }//12 5 4 3 5 5 1 1 12 12 9 9 7 1 7 2 8 11 1 2 9 10 10 5

轉(zhuǎn)載于:https://www.cnblogs.com/CQzhangyu/p/7814389.html

總結(jié)

以上是生活随笔為你收集整理的【BZOJ2791】[Poi2012]Rendezvous 倍增的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。