LCA 计算最近的公共祖先(裸版) tarjin的离线版
学习链接http://www.cnblogs.com/JVxie/p/4854719.html
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define maxn 100010 typedef long long ll; vector<int>s[maxn],q[maxn]; vector<ll>w[maxn]; int n,m,fa[maxn],k[100][100],a[maxn],b[maxn]; bool vis[maxn]; inline int read(){ int num=0,f=1; char c=getchar();; while(!isdigit(c)){if(c=='-') f=-1; c=getchar();} while(isdigit(c)){num=(num<<1)+(num<<3)+(c^48); c=getchar();} return num*f; } int find(int x){ if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } inline int un(int a,int b){ int A=find(a),B=find(b); fa[A]=B; } void lca(int x){ vis[x]=1; int num=s[x].size(); for(int i=0;i<num;i++){ int u=s[x][i]; if(!vis[u]){ lca(u); un(u,x);//和并查集不一样这里必须有顺序 } } num=q[x].size(); for(int i=0;i<num;i++){ int e=q[x][i]; if(vis[e]){ k[x][e]=find(e); k[e][x]=k[x][e];//注意双向更新 } } } inline int in(){ n=read(); m=read(); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<n;i++){ ll u,v,w; u=read(); v=read(); s[u].push_back(v); s[v].push_back(u); } for(int i=1;i<=m;i++){ a[i]=read(); b[i]=read(); q[a[i]].push_back(b[i]); q[b[i]].push_back(a[i]); } lca(1); } inline int out(){ for(int i=1;i<=m;i++) cout<<k[a[i]][b[i]]<<endl; } int main(){ in(); out(); } //9 2 //1 2 //1 3 //2 4 //2 5 //5 7 //5 8 //7 9 //3 6 //2 3 //7 8