[关闭]
@iamtts 2017-02-11T16:14:34.000000Z 字数 2726 阅读 790

寒假第四次训练-并查集&生成树

A - How Many Tables

题目大意:招待客人需要把互相认识放在一桌,给定认识关系,问最少要多少桌

解题思路:并查集,求有多少根

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. using namespace std;
  9. #define MAXN 1005
  10. int par_[MAXN],rank_[MAXN];
  11. bool hash_[MAXN];
  12. void init_(int n)
  13. {
  14. for (int i=0;i<=n;i++)
  15. {
  16. par_[i]=i;
  17. rank_[i]=0;
  18. }
  19. }
  20. int find_(int x)
  21. {
  22. if (par_[x]==x) return x;
  23. else return par_[x]=find_(par_[x]);
  24. }
  25. void unite_(int x,int y)
  26. {
  27. x=find_(x);
  28. y=find_(y);
  29. if (x==y) return;
  30. if (rank_[x]<rank_[y])
  31. {
  32. par_[x]=y;
  33. }
  34. else
  35. {
  36. par_[y]=x;
  37. if (rank_[x]==rank_[y]) rank_[x]++;
  38. }
  39. }
  40. int main()
  41. {
  42. int t,a,b,m,n,count_;
  43. scanf("%d",&t);
  44. while(t--)
  45. {
  46. count_=0;
  47. fill(hash_,hash_+MAXN,true);
  48. scanf("%d%d",&n,&m);
  49. init_(n);
  50. for (int i=0;i<m;i++)
  51. {
  52. scanf("%d%d",&a,&b);
  53. unite_(a,b);
  54. }
  55. for (int i=1;i<=n;i++)
  56. {
  57. par_[i]=find_(i);
  58. if (hash_[par_[i]])
  59. {
  60. count_++;
  61. hash_[par_[i]]=false;
  62. }
  63. }
  64. printf("%d\n",count_);
  65. }
  66. }

B - Corporative Network

题目大意:有n个互相独立的通信中心,有两种指令E和I,I a b表示将a中心连接到b中心,a与b之间距离为|a-b|,于是只剩下新的b中心,E a表示查询a到与之相连的中心的距离

解题思路:并查集,合并时将a并入b所在的集合

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. using namespace std;
  9. #define MAXN 20005
  10. pair<int,int> par_[MAXN];
  11. void init_(int n)
  12. {
  13. for (int i=0; i<=n; i++)
  14. {
  15. par_[i].first=i;
  16. par_[i].second=0;
  17. }
  18. }
  19. int find_(int x)
  20. {
  21. if (par_[x].first==x) return x;
  22. else
  23. {
  24. int parent=find_(par_[x].first);
  25. par_[x].second+=par_[par_[x].first].second;
  26. par_[x].first=parent;
  27. return parent;
  28. }
  29. }
  30. void unite_(int x,int y)
  31. {
  32. par_[x].first=y;
  33. par_[x].second+=abs(x-y)%1000;
  34. }
  35. int main()
  36. {
  37. int t,a,b,n;
  38. char ch;
  39. scanf("%d",&t);
  40. while(t--)
  41. {
  42. scanf("%d",&n);
  43. init_(n);
  44. while (getchar(),(ch=getchar())!='O')
  45. {
  46. if (ch=='I')
  47. {
  48. scanf("%d%d",&a,&b);
  49. unite_(a,b);
  50. }
  51. if (ch=='E')
  52. {
  53. scanf("%d",&a);
  54. find_(a);
  55. printf("%d\n",par_[a].second);
  56. }
  57. }
  58. }
  59. }

C - 卿学姐与诡异村庄

题目大意:村庄有n人,村民有好有坏,好人说真话,坏人说假话,第i人会说某个人是好人或者坏人,问是否存在某个好人坏人的分类使得所有质控都被满足

解题思路:并查集分为两段好人n人坏人n人,i说ai为好人则i与ai要么都为好人要么都为坏人,所以合并i与ai,i+n与ai+n,i说ai为坏人则i好ai坏或者i坏ai好,合并i与ai+n还有i+n与ai。若存在合理分类那么对于任意i,i与i+n是相反的。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. using namespace std;
  9. #define MAXN 100005
  10. int par[MAXN<<1],rank_[MAXN<<1];
  11. //pair<int,int> a[MAXN];
  12. void init_(int n)
  13. {
  14. for (int i=0; i<=n; i++)
  15. {
  16. par[i]=i;
  17. rank_[i]=0;
  18. }
  19. }
  20. int find_(int n)
  21. {
  22. if (par[n]==n) return n;
  23. else
  24. return par[n]=find_(par[n]);
  25. }
  26. bool same(int x,int y)
  27. {
  28. return find_(x)==find_(y);
  29. }
  30. void unite_(int x,int y)
  31. {
  32. int m=find_(x),n=find_(y);
  33. if (m==n) return;
  34. if (rank_[m]<rank_[n])
  35. par[m]=n;
  36. else
  37. {
  38. par[n]=m;
  39. if (rank_[m]==rank_[n]) rank_[m]++;
  40. }
  41. }
  42. int main()
  43. {
  44. int t,a,b,n,ai,flag=0;
  45. while(~scanf("%d",&n))
  46. {
  47. flag=0;
  48. init_(n<<1);
  49. for (int i=1; i<=n; i++)
  50. {
  51. scanf("%d%d",&ai,&t);
  52. if (t==1)
  53. {
  54. unite_(i,ai);
  55. unite_(i+n,ai+n);
  56. }
  57. if (t==2)
  58. {
  59. unite_(i,ai+n);
  60. unite_(i+n,ai);
  61. }
  62. }
  63. for (int i=1; i<=n; i++)
  64. {
  65. if (find_(i)==find_(i+n))
  66. {
  67. flag=1;
  68. printf("One face meng bi\n");
  69. break;
  70. }
  71. }
  72. if (flag==0) printf("Time to show my power\n");
  73. }
  74. }

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注