最裸地LCA,今天看了郭华阳的论文,顺便网上搜了些资料,学了学LCA转化为RMQ问题的解法。实现过程各种错,最后debug好长时间,最后被hack哥、模板帝万能的bin哥(Kuangbin)给改对了,Orz。。。。。。
/********************** * author:crazy_石头 * Pro:POJ 1330 * algorithm:LCA RMQ * Time:47ms * Judge Status:Accepted ***********************/ #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <set> #include <vector> #include <cmath> using namespace std; #define rep(i,h,n) for(int i=(h);i<=(n);i++) #define ms(a,b) memset((a),(b),sizeof(a)) const int maxn=100000+5; int head[maxn]; bool indegree[maxn];//从入度为0的点即根开始dfs; struct Edge { int to,next; }edge[maxn<<1]; int cnt,n; inline int min(int a,int b) { return a<b?a:b; } inline int max(int a,int b) { return a>b?a:b; } inline void addedge(int u,int v) { edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } inline void init() { ms(head,-1); cnt=0; } int pos[maxn];//结点在搜索顺序数组中最先出现的位置(下标) int depth[maxn<<1];//结点在搜索树中的深度,与e相对应 int e[maxn<<1];//结点在出现的顺序数组重复的也要记录 int index; int dp[maxn<<1][20];//RMQ数组; inline void dfs(int u,int dep) { e[++index]=u;//存入各个节点; depth[index]=dep; if(!pos[u]) pos[u]=index;//结点最先出现的话存入数组pos中; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; dfs(v,dep+1); e[++index]=u; depth[index]=dep;//回溯时也要标记上这个点; } } inline void input() { init(); index=0; ms(pos,0); ms(indegree,0); scanf("%d",&n); rep(i,1,n-1) { int u,v; scanf("%d%d",&u,&v); addedge(u,v);//添加有向边u到v; indegree[v]=1; } rep(i,1,n) { if(!indegree[i]) { dfs(i,0); break; } } } //RMQ数组预处理过程 inline void RMQ(int cur) { rep(i,1,cur) dp[i][0]=i;//dp数组存储下标; rep(j,1,20) { for(int i=1;i<=cur;i++) { if(i+(1<<j)-1<=cur) dp[i][j]=depth[dp[i][j-1]]<depth[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1]; } } } inline int query(int st,int ed)//RMQ区间内的查询; { int x=pos[st],y=pos[ed]; if(x>y)//x、y分别为左右端点; swap(x,y); int k=(int)(log(double(y-x+1))/log(2.0)); int id=depth[dp[x][k]]<depth[dp[y-(1<<k)+1][k]]?dp[x][k]:dp[y-(1<<k)+1][k];//最小值下标 return e[id]; } int main() { int t; scanf("%d",&t); while(t--) { input(); RMQ(index); int u,v; scanf("%d%d",&u,&v); printf("%d\n",query(u,v)); } return 0; } |
* This source code was highlighted by YcdoiT. ( style: Default )