LCA 入门
来源:互联网 发布:矩阵制组织结构的特点 编辑:程序博客网 时间:2024/06/11 02:20
LCA:一个树,给你两个点,问这两个点的最近公共祖先
方法一:dfs,直接先将一个点的祖先求出来,再看另外一个点祖先什么时候与之相遇(用一个标记数组),这样的话,每个询问都是n的时间复杂度
时间复杂度为o(q*n)
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 10005;int father[maxn],vis[maxn];int main(){ int n,i,j,k,sum,a,b,t,x,y; scanf("%d",&t); while(t--) { scanf("%d",&n); memset(vis,0,sizeof(vis)); memset(father,-1,sizeof(father)); for(i=1;i<n;i++) { scanf("%d %d",&x,&y); father[y]=x; } scanf("%d %d",&a,&b); while(b!=-1) { vis[b]=1; b=father[b]; } while(!vis[a]) a=father[a]; printf("%d\n",a); } return 0;}
法二:tarjian离线法(离线处理,就是将所有m个询问都存起来,然后一起输出)时间复杂度为n+q
int getf(int k){ if(k==f[k]) return k; else return f[k]=getf(f[k]);}void uin(int a,int b){ int x=getf(a),y=getf(b); if(x!=y) f[y]=x;}//这里的f和anc数组是不一样的。//最主要的竟然是anc数组。。//因为f中存的是最终的爸爸是谁,anc存的是当前i的上一个爸爸是谁void Tarjan(int u){ anc[u]=u; for(int i=head[u];i>-1;i=edge[i].pre) { node e=edge[i]; if(!vis[e.to]) { vis[e.to]=1; Tarjan(e.to); uin(u,e.to); } } col[u]=1; for(int i=hq[u];i>-1;i=q[i].pre) { node e=q[i]; if(!col[e.to]) continue; ans[e.id]=d[u]+d[e.to]-2*d[f[getf(e.to)]];//不能直接f[e.to],因为这里确保是最上面的祖先,因为uin的时候f[y]=x,但是以y为爸爸的孩子们的爸爸还没有改到x~ }}
法三:ST在线求LCA 又偷队友代码
#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <iostream>#include <string>#include <vector>using namespace std;const int maxn = 10010;struct node{ int to,pre;}e[maxn*2];int vis[maxn];int dep[maxn];int head[maxn];int dp[maxn][30];int h=0;void init(){ h=0; memset(e,0,sizeof(e)); memset(vis,0,sizeof(vis)); memset(dep,0,sizeof(dep)); memset(head,-1,sizeof(head));}void add(int from,int to){ e[h].to=to,e[h].pre=head[from];head[from]=h;h++;}void dfs(int u,int fa,int d){ dep[u]=d; for(int i=head[u];i>-1;i=e[i].pre) { node t=e[i]; if(t.to==fa) continue; dp[t.to][0]=u; dfs(t.to,u,d+1); }}void rmp(int n){ for(int i=1;i<20;i++) { for(int j=1;j<=n;j++) { if((1<<i)>dep[j])continue; int k=dp[j][i-1];dp[j][i]=dp[k][i-1]; } }}int query(int x,int y){ if(dep[x]>dep[y]) swap(x,y); for(int j=20;j>=0&&dep[x]!=dep[y];j--) { if(dep[y]-(1<<j)<dep[x]) continue; y=dp[y][j]; } if(x==y) return x; for(int j=20;j>=0;j--) { if(dep[x]-(1<<j)<0||dp[x][j]==dp[y][j]) continue; x=dp[x][j],y=dp[y][j]; } return dp[x][0];}int main(){ int T; scanf("%d",&T); while(T--){ init(); int n; scanf("%d",&n); for(int i=1;i<n;i++) { int x,y; scanf("%d %d",&x,&y); add(x,y),add(y,x);vis[y]=1; } for(int i=1;i<=n;i++) { if(!vis[i]) { dfs(i,i,0); break; } } rmp(n); int x,y; scanf("%d %d",&x,&y); printf("%d\n",query(x,y)); } return 0;}
阅读全文
0 0
- LCA 入门
- LCA入门学习
- hdu 2586 lca入门
- 倍增法lca 入门——CODE[VS] 4605 LCA
- POJ 1330 LCA入门题(Tarjan)
- Nearest Common Ancestors LCA的基本入门
- hdu2586 LCA入门(在线算法ST)
- LCA
- LCA
- lca
- LCA
- LCA
- lca
- LCA
- LCA
- LCA
- LCA
- LCA
- offer
- java properties文件的读写操作
- offer
- 测试工具功能介绍
- offer
- LCA 入门
- vim:一些命令和选项 filetype, autocmd, map,tabstop等
- Offer
- 微信小程序8 位置与设备api
- String转int 非库函数 Java
- Java Jersey web service 总结
- vim:学习资料——把vim打造成 IDE
- ZooKeeper学习之zookeeper的ACL(AUTH)
- JDBC的使用