POJ-1330--Nearest Common Ancestors(离线LCA)
LCA离线算法
它需要一次输入所有的询问,然后有根节点开始进行深度优先遍历(DFS),在深度优先遍历的过程中,进行并查集的操作,同时查询询问,返回结果。
题意:
求A ,B两点的最近公共祖先
分析:
dfs+并查集
// File Name: 1330.cpp // Author: Zlbing // Created Time: 2013年08月18日 星期日 16时11分18秒 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) const int MAXN=1e4+100; vector<int> G[MAXN],ques[MAXN]; int vis[MAXN]; int f[MAXN]; int in[MAXN]; int find(int x) { return f[x]==x?x:f[x]=find(f[x]); } void LCA(int u,int fa) { for(int i=0;i<(int)G[u].size();i++) { int v=G[u][i]; if(v==fa)continue; LCA(v,u); f[find(v)]=u; } vis[u]=1; for(int i=0;i<(int)ques[u].size();i++) { int v=ques[u][i]; if(vis[v]) { int ans=find(v); printf("%d\n",ans); } } } int main() { int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); REP(i,1,n) { G[i].clear(); ques[i].clear(); f[i]=i; } CL(in,0); CL(vis,0); int a,b; REP(i,1,n-1) { scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); in[b]++; } scanf("%d%d",&a,&b); ques[a].push_back(b); ques[b].push_back(a); for(int i=1;i<=n;i++) { if(!in[i]) LCA(i,-1); } } return 0; }