codeforces 208 E 時間戳記 倍增法求LCA

來源:互聯網
上載者:User

連結:http://www.codeforces.com/problemset/problem/208/E

題意:給你一個森林,m個詢問:v,p

求有多少個點(除v外) 與 v的第p個祖先相同

這個題首先要解決找某個點的第p個祖先的問題,可以採用倍增法

記錄一個二維數組p[u][i]表示u的第2^i個祖先,那麼通過這個數組我們就可以知道u的上面任意深度(相對於u)祖先是誰(巧妙的利用二進位)

具體求法和用法見下,還可以找LCA的


/*2^17=131072;2^18=262144;*/const int POW = 18;void dfs(int u,int fa){d[u]=d[fa]+1;    p[u][0]=fa;for(int i=1;i<POW;i++) p[u][i]=p[p[u][i-1]][i-1];int sz=edge[u].size();for(int i=0;i<sz;i++){int v=edge[u][i];if(v==fa) continue;dfs(v,u);}}int lca( int a, int b ){if( d[a] > d[b] ) a ^= b, b ^= a, a ^= b;if( d[a] < d[b] ){int del = d[b] - d[a];for( int i = 0; i < POW; i++ ) if(del&(1<<i)) b=p[b][i];}if( a != b ){for( int i = POW-1; i >= 0; i-- ) if( p[a][i] != p[b][i] )      a = p[a][i] , b = p[b][i];a = p[a][0], b = p[b][0];}return a;}

這道題的話需要記錄  每個點的兩個時間戳記,每個深度的所有時間戳記

假設vp是v的p祖先,那麼v 的 p  Cousins就是時間戳記位於vp的兩個時間戳記之間深度為dep【v】

的點的個數

#include<cstdio>#include<cstring>#include<vector>#include<algorithm>using namespace std;const int maxn = 100010;vector<int> g[maxn];vector<int> edge[maxn];vector<int> rt;bool vis[maxn];int n,m,dfn;int in[maxn],out[maxn];int dep[maxn],p[maxn][18];int depth;void dfs(int u,int fa){vis[u]=true;in[u]=dfn++;//printf("in[%d]=%d\n",u,in[u]);dep[u]=dep[fa]+1;g[dep[u]].push_back(dfn);    p[u][0]=fa;for(int i=1;i<18;i++) p[u][i]=p[p[u][i-1]][i-1];int sz=edge[u].size();for(int i=0;i<sz;i++){int v=edge[u][i];if(v==fa) continue;dfs(v,u);}out[u]=dfn++;//printf("out[%d]=%d\n",u,out[u]);}int solve(int tfn,int d){int l=0,r=g[d].size()-1,best=-1;while(l<=r){int m=l+r>>1;if(g[d][m]<=tfn){l=m+1;  best=m;}else r=m-1;}return best+1;}int find(int v,int pp){for(int i=0;i<18;i++) if(pp&(1<<i)) v=p[v][i];return v;}int ans[maxn];int main(){while(scanf("%d",&n)!=EOF){int fa,v,pp;rt.clear();memset(p,0,sizeof(p));memset(dep,0,sizeof(dep));for(int i=0;i<=n;i++) edge[i].clear(),g[i].clear();for(int i=1;i<=n;i++){scanf("%d",&fa);if(fa==0) rt.push_back(i);else edge[fa].push_back(i);}dfn=0;depth=0;for(int i=0;i<rt.size();i++)  depth=0,dfs(rt[i],0);scanf("%d",&m);for(int i=0;i<m;i++){scanf("%d%d",&v,&pp);int vp=find(v,pp);if(!vp) ans[i]=0;else {    ans[i]=solve(out[vp],dep[v])-solve(in[vp]-1,dep[v])-1;}}for(int i=0;i<m;i++) printf("%d ",ans[i]);puts("");}return 0;}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.