当前位置:   article > 正文

one piece_娜美_01_one piece hentai

one piece hentai


LCA 模板 + poj 1330


  1. #include<iostream>
  2. #include<vector>
  3. using namespace std;
  4. const int MAX=10001;
  5. int f[MAX]; //每个节点所属的集合
  6. int r[MAX]; //r是rank(秩) 合并
  7. int indegree[MAX];//保存每个节点的入度
  8. int visit[MAX];//只有1和0,表示某节点的Id是否已处理完毕
  9. vector<int> tree[MAX],Qes[MAX];//树,查询
  10. int ancestor[MAX]; //祖先集合
  11. void init(int n)
  12. {
  13. for(int i=1;i<=n;i++)
  14. {
  15. r[i]=1; //每个节点的秩初始为1,
  16. f[i]=i; //每个节点的父节点初始为自身
  17. indegree[i]=0;
  18. visit[i]=0;
  19. ancestor[i]=0; //祖先为0
  20. tree[i].clear();
  21. Qes[i].clear();
  22. }
  23. }
  24. int find(int n) //查找n节点所在的集合
  25. {
  26. if(f[n]==n)
  27. return n;
  28. else
  29. f[n]=find(f[n]);
  30. return f[n];
  31. }//查找函数,并压缩路径
  32. int Union(int x,int y)
  33. {
  34. int a=find(x);
  35. int b=find(y);
  36. if(a==b)
  37. return 0;
  38. //相等的话,x向y合并
  39. else if(r[a]<=r[b])
  40. {
  41. f[a]=b; //两个秩相等,合并到左边的秩
  42. r[b]+=r[a]; //小的秩合并向大的秩
  43. }
  44. else
  45. {
  46. f[b]=a;
  47. r[a]+=r[b];
  48. }
  49. return 1;
  50. }//合并函数,如果属于同一分支则返回0,成功合并返回1
  51. void LCA(int u)
  52. {
  53. ancestor[u]=u;
  54. int size = tree[u].size();
  55. for(int i=0;i<size;i++)
  56. {
  57. LCA(tree[u][i]);
  58. Union(u,tree[u][i]);
  59. ancestor[find(u)]=u; //让u的父节点为u,因为回溯操作,一定保证集合的祖先是最近祖先,
  60. }
  61. visit[u]=1;
  62. size = Qes[u].size();
  63. for(int i=0;i<size;i++)
  64. {
  65. //如果已经访问了问题节点,就可以返回结果了.
  66. if(visit[Qes[u][i]]==1)
  67. {
  68. cout<<ancestor[find(Qes[u][i])]<<endl;
  69. return;
  70. }
  71. }
  72. }
  73. int main()
  74. {
  75. int cnt;
  76. int n;
  77. cin>>cnt;
  78. while(cnt--)
  79. {
  80. cin>>n;;
  81. init(n);
  82. int s,t;
  83. for(int i=1;i<n;i++)
  84. {
  85. cin>>s>>t;
  86. tree[s].push_back(t);
  87. indegree[t]++;
  88. }
  89. //这里可以输入多组询问
  90. cin>>s>>t;
  91. //相当于询问两次
  92. Qes[s].push_back(t);
  93. Qes[t].push_back(s);
  94. for(int i=1;i<=n;i++)
  95. {
  96. //寻找根节点
  97. if(indegree[i]==0)
  98. {
  99. LCA(i);
  100. break;
  101. }
  102. }
  103. }
  104. return 0;
  105. }



  1. 算法步骤:
  2. 1 由根节点开始,进行深度优先遍历,遍历到叶子节点,置其对应的visit[i] = 1;
  3. 2 将父节点与子节点进行合并(将他们置于同一个集合,详细看union代码),
  4. 然后,将集合的祖先置为当前节点。(要注意回溯的过程,一定是保证高层次的)
  5. 3 询问查询,即qes[u][i],u是查询节点之一(正好是当前节点),
  6. i是另一个查询节点,如果i此时已被处理完毕,
  7. 说明i在u的左边,那么i所在集合(并不是像有些文章说的i的父节点,这概念不正确)的祖先一定u,
  8. i的最近共同祖先(如果u,i在同一子树,则很好理解,如果u,i在不同子树,
  9. 那么i所在集合的祖先也是u的祖先(注意回溯,上升,下降));
  10. 如果i此时未被处理,说明i在u的右边,对于u,i的询问只能跳过,但是对i,u的询问可以处理。
  11. 这个是两个节点共同祖先的查询,多个的话就用前两个的查询结果与下一个组成一个查询,依次类推。


声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号