[关闭]
@zhangche0526 2017-02-25T06:28:36.000000Z 字数 3027 阅读 802

LCA

倍增法

在线算法

时间复杂度:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. using namespace std;
  6. int m,n,q,anc[100][32],deep[100];
  7. int head[100],cnt;
  8. struct mine
  9. {
  10. int to,next;
  11. }edge[100];
  12. void swap(int &a,int &b){int t=a;a=b;b=t;}
  13. void add(int x,int y)
  14. {
  15. cnt++;
  16. edge[cnt].to=y;
  17. edge[cnt].next=head[x];
  18. head[x]=cnt;
  19. }
  20. void dfs(int now,int from)
  21. {
  22. for(int tmp=head[now];tmp!=0;tmp=edge[tmp].next)
  23. {
  24. if(edge[tmp].to==from) continue;//遍历无向图时防止死循环
  25. deep[edge[tmp].to]=deep[now]+1;
  26. dfs(edge[tmp].to,now);
  27. anc[edge[tmp].to][0]=now;
  28. }
  29. }
  30. void ready()
  31. {
  32. for(int i=1;(1<<i)<=n;i++)
  33. for(int j=1;j<=n;j++)
  34. anc[j][i]=anc[anc[j][i-1]][i-1];
  35. }
  36. int getlca(int x,int y)
  37. {
  38. if(deep[x]<deep[y]) swap(x,y);
  39. int maxlogn=floor(log(n)/log(2));
  40. for(int i=maxlogn;i>=0;i--)
  41. if(deep[x]-(1<<i)>=deep[y])
  42. x=anc[x][i];
  43. if(x==y) return x;
  44. for(int i=maxlogn;i>=0;i--)
  45. if(anc[x][i]!=anc[y][i])
  46. {
  47. x=anc[x][i];y=anc[y][i];
  48. }
  49. return anc[x][0];
  50. }
  51. int main()
  52. {
  53. freopen("lca.in", "r", stdin);
  54. cin >> n >> m;
  55. for (int i = 1; i <= m; i++)
  56. {
  57. int u, v;
  58. cin >> u >> v;
  59. add(u, v);
  60. add(v, u);
  61. }
  62. dfs(1,1);
  63. ready();
  64. for (int i = 1; i <= n; i++)
  65. for (int j = i; j <= n; j++)
  66. cout << i << " " << j << " " << getlca(i, j) << endl;
  67. return 0;
  68. }

Tarjan法

离线算法

  1. #include<cstdio>
  2. using namespace std;
  3. int n,m,root,edge_num,ask_num;
  4. int fa[500010],head[1200000],h1[1200000],ans[500010];
  5. bool b[500010];
  6. struct E{
  7. int next,to;
  8. }edge[1200000];
  9. struct A{
  10. int next,to,num;
  11. }ask[1200000];
  12. void addedge(int x,int y){
  13. edge[++edge_num].next=head[x];
  14. edge[edge_num].to=y;
  15. head[x]=edge_num;
  16. }
  17. void addask(int x,int y,int z){
  18. ask[++ask_num].next=h1[x];
  19. ask[ask_num].to=y;
  20. ask[ask_num].num=z;
  21. h1[x]=ask_num;
  22. }
  23. int Find(int x){
  24. if(fa[x]!=x) fa[x]=Find(fa[x]);
  25. return fa[x];
  26. }
  27. /*void Union(int a,int b){
  28. a=Find(a);b=Find(b);
  29. fa[a]=b;
  30. }*/
  31. void LCA(int x){
  32. b[x]=1;
  33. fa[x]=x;
  34. int j,u;
  35. for(j=head[x];j;j=edge[j].next){
  36. u=edge[j].to;
  37. if(!b[u]){
  38. LCA(u);
  39. fa[u]=x;
  40. }
  41. }
  42. int k;
  43. for(j=h1[x];j;j=ask[j].next){
  44. u=ask[j].to;
  45. k=ask[j].num;
  46. if(b[u]){
  47. ans[k]=Find(u);
  48. }
  49. }
  50. }
  51. void out(){
  52. for(int o=1;o<=m;o++){
  53. printf("%d\n",ans[o]);
  54. }
  55. }
  56. int main(){
  57. scanf("%d%d%d",&n,&m,&root);
  58. int i,ask1,ask2,a1,b1;
  59. for(i=1;i<=n-1;i++){
  60. scanf("%d%d",&a1,&b1);
  61. addedge(a1,b1);addedge(b1,a1);
  62. }
  63. for(i=1;i<=m;i++){
  64. scanf("%d%d",&ask1,&ask2);
  65. addask(ask1,ask2,i);
  66. addask(ask2,ask1,i);
  67. }
  68. LCA(root);
  69. out();
  70. return 0;
  71. }

RMQ法

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. using namespace std;
  6. const int MAXN=500000,MAXM=100;
  7. int a[MAXN+1],pa=0;int na[MAXN+1];
  8. int f[MAXN+1][MAXM+1];
  9. int head[MAXN+1],ecnt;
  10. struct node{int to,next;} edge[MAXN+1];
  11. void add(int x,int y)
  12. {
  13. ecnt++;
  14. edge[ecnt].to=y;
  15. edge[ecnt].next=head[x];
  16. head[x]=ecnt;
  17. }
  18. void Init()
  19. {
  20. for (int i = 1; i <= pa; i++)
  21. f[i][0] = a[i];
  22. for (int k = 1; (1 << k) <= pa; k++)
  23. for (int i = 1; i + (1 << k) - 1 <= pa; i++)
  24. f[i][k] = min(f[i][k - 1], f[i + (1 << (k - 1))][k - 1]);
  25. }
  26. int RMQ(int l, int r)
  27. {
  28. int k = 0;
  29. while( (1 << (k + 1)) <= r - l + 1 ) k++;
  30. return min( f[l][k], f[r - (1 << k) + 1][k] );
  31. }
  32. void dfs(int x,int d)
  33. {
  34. for(int tmp=head[x];tmp;tmp=edge[tmp].next)
  35. {
  36. a[++pa]=d;na[pa]=x;
  37. dfs(edge[tmp].to,d+1);
  38. }
  39. a[++pa]=d;na[pa]=x;
  40. }
  41. int main()
  42. {
  43. int u,v,N,M,S,x,y,xp,yp;
  44. cin>>N>>M>>S;
  45. for(int i=1;i<=N-1;i++)
  46. cin>>u>>v,add(v,u);
  47. dfs(S,1);
  48. Init();
  49. for(int i=1;i<=M;i++)
  50. {
  51. cin>>x>>y;
  52. for(int i=1;i<=pa;i++) if(na[i]==x){xp=i;break;}
  53. for(int i=1;i<=pa;i++) if(na[i]==y){yp=i;break;}
  54. if(xp>yp) swap(xp,yp);
  55. cout<<na[RMQ(xp,yp)]<<endl;
  56. }
  57. return 0;
  58. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注