[关闭]
@lychee123 2017-03-04T19:33:37.000000Z 字数 2758 阅读 1150

LCA小结

模板 LCA


暴力法

  1. #include<stdio.h>
  2. #include<iostream>
  3. #include<string.h>
  4. #include<algorithm>
  5. using namespace std;
  6. const int N=502;
  7. vector<int>G[N];///存点,G[1]表示与1相连的点
  8. int fa[N],dep[N];///i节点的父节点,i节点的深度
  9. void dfs(int u,int f,int d)///u节点,u节点的父亲节点,u节点的深度
  10. {
  11. fa[u]=f;
  12. dep[u]=d;
  13. for(int i=0;i<G[u].size();i++)
  14. {
  15. int v=G[u][i];
  16. if(v==f)
  17. continue;
  18. dfs(v,u,d+1);
  19. }
  20. }
  21. void init()
  22. {
  23. dfs(root,-1,0);
  24. }
  25. int lca(int u,int v)
  26. {
  27. if(dep[u]>dep[v])///保证u的深度小于v的深度
  28. swap(u,v);
  29. while(dep[v]>dep[u])///使uv的深度一样
  30. v=fa[v];
  31. while(u!=v)///不断往上,直到u=v,得到lca(u,v)
  32. {
  33. u=fa[u];
  34. v=fa[v];
  35. }
  36. return u;
  37. }

倍增法

  1. #include<stdio.h>
  2. #include<iostream>
  3. #include<string.h>
  4. #include<algorithm>
  5. using namespace std;
  6. const int N=502;
  7. const int LOG=18;
  8. vector<int>G[N];///存点,G[1]表示与1相连的点
  9. int p[LOG][N],dep[N];///p[i][j]表示距离j 往上走2^i个点的父节点,i节点的深度
  10. void dfs(int u,int f,int d)
  11. {
  12. dep[u]=d;
  13. p[0][u]=f;
  14. for(int i=0;i<G[u].size();i++)
  15. {
  16. int v=G[u][i];
  17. if(v==f)
  18. continue;
  19. dfs(v,u,d+1);
  20. }
  21. }
  22. void init()
  23. {
  24. dfs(root,-1,0);
  25. for(int i=0;i<LOG-1;i++)
  26. {
  27. for(int j=1;j<=n;j++)
  28. {
  29. if(p[i][j]<0)
  30. p[i+1][j]=-1;
  31. else
  32. p[i+1][j]=p[i][p[i][j]];
  33. }
  34. }
  35. }
  36. int lca(int u,int v)
  37. {
  38. if(dep[u]>dep[v])
  39. swap(u,v);
  40. for(int i=0;i<LOG;i++)
  41. if(dep[v]-dep[u]>>i&1)
  42. v=p[i][v];
  43. if(u==v)
  44. return u;
  45. for(int i=LOG-1;i>=0;i--)
  46. {
  47. if(p[i][u]!=p[i][v])
  48. {
  49. u=p[i][u];
  50. v=p[i][v];
  51. }
  52. }
  53. return p[0][u];
  54. }

  1. #include<stdio.h>
  2. #include<iostream>
  3. #include<string.h>
  4. #include<vector>
  5. #include<algorithm>
  6. using namespace std;
  7. const int N=40004;
  8. const int LOG=20;
  9. int p[LOG][N],dep[N];///p[i][j]表示距离j 往上走2^i个点的父节点,i节点的深度
  10. int dis[N];///距离
  11. int n;
  12. struct node
  13. {
  14. int id,l;
  15. node(int idid=0,int ll=0)
  16. {
  17. id=idid;
  18. l=ll;
  19. }
  20. };
  21. vector<node>G[N];///存点,G[1]表示与1相连的点
  22. void dfs(int u,int f,int d)
  23. {
  24. dep[u]=d;
  25. p[0][u]=f;
  26. for(int i=0;i<G[u].size();i++)
  27. {
  28. int v=G[u][i].id;
  29. if(v==f)
  30. continue;
  31. dis[v]=dis[u]+G[u][i].l;
  32. dfs(v,u,d+1);
  33. }
  34. }
  35. void init()
  36. {
  37. memset(dis,0,sizeof(dis));
  38. dfs(1,-1,0);
  39. for(int i=0;i<LOG-1;i++)
  40. {
  41. for(int j=1;j<=n;j++)
  42. {
  43. if(p[i][j]<0)
  44. p[i+1][j]=-1;
  45. else
  46. p[i+1][j]=p[i][p[i][j]];
  47. }
  48. }
  49. }
  50. int lca(int u,int v)
  51. {
  52. if(dep[u]>dep[v])
  53. swap(u,v);
  54. for(int i=0;i<LOG;i++)
  55. {
  56. if(dep[v]-dep[u]>>i&1)
  57. v=p[i][v];
  58. }
  59. if(u==v)
  60. return u;
  61. for(int i=LOG-1;i>=0;i--)
  62. {
  63. if(p[i][u]!=p[i][v])
  64. {
  65. u=p[i][u];
  66. v=p[i][v];
  67. }
  68. }
  69. return p[0][u];
  70. }
  71. int main()
  72. {
  73. int t,i,j,m,x,y,l,a,b;
  74. scanf("%d",&t);
  75. while(t--)
  76. {
  77. scanf("%d%d",&n,&m);
  78. for(i=0;i<n;i++)
  79. G[i].clear();
  80. for(i=0;i<n-1;i++)
  81. {
  82. scanf("%d%d%d",&x,&y,&l);
  83. G[x].push_back(node(y,l));
  84. G[y].push_back(node(x,l));
  85. }
  86. init();
  87. for(i=0;i<m;i++)
  88. {
  89. scanf("%d%d",&a,&b);
  90. printf("%d\n",dis[a]+dis[b]-2*dis[lca(a,b)]);
  91. }
  92. }
  93. return 0;
  94. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注