5 1 2 1 3 3 4 4 5 5 1 2 2 3 3 4 3 5 1 5
1 1 3 3 1HintBe careful about stack overflow.方法一:
树链剖分维护lca,这样速度比较快,通过RMQ维护连续的LCA值
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <ctime> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define inf -0x3f3f3f3f #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mem0(a) memset(a,0,sizeof(a)) #define mem1(a) memset(a,-1,sizeof(a)) #define mem(a, b) memset(a, b, sizeof(a)) typedef long long ll; const int maxn=301010; int tot; vector<int>G[maxn]; int siz[maxn],son[maxn],fa[maxn],deep[maxn],top[maxn],id[maxn],dp[maxn][20];; void init(int n){ tot=0; for(int i=1;i<=n;i++) G[i].clear(); } void dfs1(int u,int dep){ deep[u]=dep; siz[u]=1,son[u]=0; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa[u]) continue; fa[v]=u; dfs1(v,dep+1); if(siz[son[u]]<siz[v]){ son[u]=v; } siz[u]+=siz[v]; } } void dfs2(int u,int tp){ top[u]=tp; id[u]=++tot; if(son[u]!=0){ dfs2(son[u],tp); } for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(son[u]==v||v==fa[u]) continue; dfs2(v,v); } } int Query(int u,int v){ int f1=top[u],f2=top[v]; while(f1!=f2){ if(deep[f1]<deep[f2]){ swap(f1,f2); swap(u,v); } u=fa[f1]; f1=top[u]; } if(deep[u]>deep[v]) return v; return u; } int RMQ(int L,int R){ int k=log2(R-L+1); return Query(dp[L][k],dp[R-(1<<k)+1][k]); } int main(){ int n,Q; while(scanf("%d",&n)!=EOF){ init(n); int u,v; for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } fa[1]=0,siz[0]=0; dfs1(1,0); dfs2(1,0); for(int i=1;i<=n;i++) dp[i][0]=i; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) dp[i][j]=Query(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); scanf("%d",&Q); while(Q--){ scanf("%d%d",&u,&v); printf("%d\n",RMQ(u,v)); } } return 0; }
方法二:利用倍增法维护LCA,这样的方法比较慢
#include<bits/stdc++.h>using namespace std; const int maxn=300000+1000; const int DEG=20; int head[maxn],tot,fa[maxn][DEG]; int dp[maxn][DEG]; int deg[maxn]; struct Edge{ int to,next; }e[2*maxn]; void addedge(int u,int v){ e[tot].to=v; e[tot].next=head[u]; head[u]=tot++; } void init(){ memset(head,-1,sizeof(head)); tot=0; } void bfs(int root){ fa[root][0]=root; deg[root]=0; queue<int>Q; Q.push(root); while(!Q.empty()){ int tmp=Q.front(); Q.pop(); for(int i=1;i<DEG;i++) fa[tmp][i]=fa[fa[tmp][i-1]][i-1];//i的第2^j祖先就是i的第2^(j-1)祖先的第2^(j-1)祖先 for(int i=head[tmp];i!=-1;i=e[i].next){ int v=e[i].to; if(fa[tmp][0]==v) //这个点是tmp的父亲 continue; fa[v][0]=tmp; deg[v]=deg[tmp]+1; Q.push(v); } } } int LCA(int u,int v){ if(deg[u]>deg[v]) swap(u,v); int hu=deg[u],hv=deg[v]; int tu=u,tv=v; for(int det=hv-hu,i=0;det;det>>=1,i++) if(det&1) tv=fa[tv][i]; if(tu==tv) return tu; for(int i=DEG-1;i>=0;i--){ if(fa[tu][i]==fa[tv][i]) continue; tu=fa[tu][i]; tv=fa[tv][i]; } return fa[tu][0]; } int RMQ(int L,int R){ int k=log2(R-L+1); return LCA(dp[L][k],dp[R-(1<<k)+1][k]); } int main(){ int n,u,v,Q; while(scanf("%d",&n)!=EOF){ init(); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } bfs(1); for(int i=1;i<=n;i++) dp[i][0]=i; for(int j=1;(1<<j)<=n;j++)