POJ - 1330 Nearest Common Ancestors(树上倍增/树链剖分求LCA)
生活随笔
收集整理的這篇文章主要介紹了
POJ - 1330 Nearest Common Ancestors(树上倍增/树链剖分求LCA)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出一棵有根樹,我們需要求出兩個點的lca
題目分析:因為題目說了是有根樹,所以我們在建圖的時候直接建有向圖就好了,并且記錄一下每個點的入度,建完圖后找一下入度為0的點,就是根節點了,然后建樹,就可以直接套模板求lca了,這里掛兩個模板,一個是樹上倍增,一個是樹鏈剖分,都寫了一下練練手:
樹上倍增:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e4+100;int n;int limit;int in[N];vector<int>node[N];int dp[N][20];int deep[N];void dfs(int u,int f,int dep) {deep[u]=dep;dp[u][0]=f;for(int i=1;i<=limit;i++)dp[u][i]=dp[dp[u][i-1]][i-1];for(int i=0;i<node[u].size();i++){int v=node[u][i];if(v==f)continue;dfs(v,u,dep+1);} }int LCA(int x,int y) {if(deep[x]<deep[y])swap(x,y);for(int i=limit;i>=0;i--)if(deep[x]-deep[y]>=(1<<i))x=dp[x][i];if(x==y)return x;for(int i=limit;i>=0;i--)if(dp[x][i]!=dp[y][i]){x=dp[x][i];y=dp[y][i];}return dp[x][0]; }void init() {for(int i=1;i<=n;i++){node[i].clear();in[i]=0;}limit=log2(n)+1; }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int w;scanf("%d",&w);while(w--){scanf("%d",&n);init();for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);in[v]++;}for(int i=1;i<=n;i++)if(!in[i]){dfs(i,-1,0);break;}int u,v;scanf("%d%d",&u,&v);printf("%d\n",LCA(u,v));}return 0; }樹鏈剖分:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e4+100;int n;int in[N];vector<int>node[N];int deep[N],fa[N],son[N],num[N];//深度、父節點、重兒子節點、子樹大小int top[N];//重鏈最上面的點void dfs1(int u,int f,int dep) {deep[u]=dep;fa[u]=f;son[u]=-1;num[u]=1;for(int i=0;i<node[u].size();i++){int v=node[u][i];if(v==f)continue;dfs1(v,u,dep+1);num[u]+=num[v];if(son[u]==-1||num[son[u]]<num[v])son[u]=v;} }void dfs2(int u,int f,int root) {top[u]=root;if(son[u]!=-1)dfs2(son[u],u,root);for(int i=0;i<node[u].size();i++){int v=node[u][i];if(v==f||v==son[u])continue;dfs2(v,u,v);} }int LCA(int x,int y) {while(top[x]!=top[y]){if(deep[top[x]]>deep[top[y]])//注意這里,deep里面還要套一個top,比較一下重鏈頂端的節點深度x=fa[top[x]];elsey=fa[top[y]];}return deep[x]>deep[y]?y:x; }void init() {for(int i=1;i<=n;i++){node[i].clear();in[i]=0;} }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int w;scanf("%d",&w);while(w--){scanf("%d",&n);init();for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);in[v]++;}for(int i=1;i<=n;i++)if(!in[i]){dfs1(i,-1,0);dfs2(i,-1,i);break;}int u,v;scanf("%d%d",&u,&v);printf("%d\n",LCA(u,v));}return 0; }?
總結
以上是生活随笔為你收集整理的POJ - 1330 Nearest Common Ancestors(树上倍增/树链剖分求LCA)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 979D Ku
- 下一篇: CodeForces - 208E Bl