• 发现它,抓住它


    描述
    一个城市中有两个犯罪团伙A和B,你需要帮助警察判断任意两起案件是否是同一个犯罪团伙所为,警察所获得的信息是有限的。假设现在有N起案件(N<=100000),编号为1到N,每起案件由团伙A或团伙B所为。你将按时间顺序获得M条信息(M<=100000),这些信息分为两类:
    1、 D [a] [b]
    其中[a]和[b]表示两起案件的编号,这条信息表明它们属于不同的团伙所为

    2、A [a] [b]
    其中[a]和[b]表示两起案件的编号,这条信息需要你回答[a]和[b]是否是同一个团伙所为
    注意你获得信息的时间是有先后顺序的,在回答的时候只能根据已经接收到的信息做出判断。

    输入
    第一行是测试数据的数量T(1<=T<=20)。
    每组测试数据的第一行包括两个数N和M,分别表示案件的数量和信息的数量,其后M行表示按时间顺序收到的M条信息。

    输出
    对于每条需要回答的信息,你需要输出一行答案。如果是同一个团伙所为,回答”In the same gang.”,如果不是,回答”In different gangs.”,如果不确定,回答”Not sure yet.”。

    1. 样例输入
    2. 1
    3. 5 5
    4. A 1 2
    5. D 1 2
    6. A 1 2
    7. D 2 4
    8. A 1 4
    9. 样例输出
    10. Not sure yet.
    11. In different gangs.
    12. In the same gang.

       我们先来讲一下这道题的思路,我们输入之后,首先将1~N这N个数字插入到并查集中,然后如果输入的是‘D’,那么就unionSet进行合并(一个集合内的所有元素代表这些犯罪团伙都不是一个团伙),如果输入的是‘A’,那么进行find函数查找a和b的所在集合,我们就只需要判断他们的所在集合是否相同即可。

      如果不相同,代表不确定,输出Not sure yet.,如果a和b的父节点是相同的(代表他们是否是同一个集合),如果相同,就输出In the same gang.,如果不是就输出In different gangs.。

    并查集和路径压缩算法的应用:
    1、 father[i] 表示 i 的父节点是谁; relation[i] 表示 i 这个节点和他父节点的关系,0表示同一个犯罪组织,1表示不同。
    2、初始化将每个节点的父节点赋值为自身, relation 也理所当然的赋值为0(相同)。
    3、 Find(int x) 函数返回值为 x 的祖先。采用路径压缩。由于是递归,途中不断将这条路上上面节点接到祖先节点,并一路修改 relation 的值,直到最下面的节点接到祖先节点。
    (1)如果 x 的父节点就是祖先节点,那么 father[x] 的 r 为 0,x 的 r 不需要改变;
    (2)否则,有几种情况:
    ·r[ f[x] ] = 1,r[x] = 1,即 x 和他父亲不同,x 父亲和 x 父亲的父亲(祖先)也不同,所以 x 和 祖先相同
    ·r[ f[x] ] = 1,r[x] = 0,即 x 和他父亲不同,x 父亲和 x 父亲的父亲(祖先)相同,所以 x 和 祖先不同
    ·r[ f[x] ] = 0,r[x] = 1,即 x 和他父亲相同,x 父亲和 x 父亲的父亲(祖先)不同,所以 x 和 祖先不同
    ·r[ f[x] ] = 0,r[x] = 0,即 x 和他父亲相同,x 父亲和 x 父亲的父亲(祖先)也相同,所以 x 和 祖先相同
    所以总结后有这样一个公式: r[x] = (r[x] + r[ f[x] ]) % 2;
    4、输入命令时,如果是 D,表示这两个案件是不同团伙所做,那么把 x 的祖先归并到 y 的祖先下面,并修改 relation的值。由于查找祖先节点时,有路径压缩过程,所以归并时 x 已经直接接到他的祖先节点上。
    由于 x 和 y 的种类不同,考虑如下情况:
    (1)若 y 和 y 的祖先节点 fy 相同, r[y] = 0;则 x 和 fy不同。若 r[x] = 1, x 和 fx 不同,则 fx 和 fy 相同,
    即 r[fx] = 0;同理可得当 r[x] = 0,r[fx] = 1;所以 r[fx] = 1 - r[x];
    (2)若 y 和 fy 不同,同上分析,可得 r[fx] = r[x].

    发现它,抓住它:

    1. #include
    2. using namespace std;
    3. template<class T>
    4. struct DisjointSet{
    5. int *parent;
    6. T *data;
    7. mapint> m;
    8. int capacity;
    9. int size;
    10. DisjointSet(int max=1000){
    11. capacity=max;
    12. size=0;
    13. parent=new int[max+1];
    14. data=new T[max+1];
    15. }
    16. ~DisjointSet(){
    17. delete [] parent;
    18. delete [] data;
    19. }
    20. bool insert(T x){
    21. if(size==capacity) return false;
    22. size++;
    23. data[size]=x;
    24. parent[size]=-1;
    25. m[x]=size;
    26. return true;
    27. }
    28. int getIndex(T x){
    29. for(int i=1;i<=size;i++)
    30. if(data[i]==x)
    31. return i;
    32. return -1;
    33. }
    34. int find(T x){
    35. typename mapint>::iterator it;
    36. it=m.find(x);
    37. if(it==m.end()) return -1;
    38. int i,rt;
    39. i=rt=it->second;
    40. while(parent[rt]>0)
    41. rt=parent[rt];
    42. return rt;
    43. }
    44. void unionSet(T x,T y){
    45. int rx,ry;
    46. rx=find(x);
    47. ry=find(y);
    48. if(rx==-1||ry==-1) return ;
    49. if(rx==ry) return ;
    50. if(parent[rx]
    51. parent[rx]+=parent[ry];
    52. parent[ry]=rx;
    53. }
    54. else{
    55. parent[ry]+=parent[rx];
    56. parent[rx]=ry;
    57. }
    58. find(x);
    59. find(y);
    60. }
    61. };
    62. int main(){
    63. int t;
    64. cin>>t;
    65. while(t--){
    66. DisjointSet<int> s;
    67. int n,m;
    68. cin>>n>>m;
    69. for(int i=1;i<=n;i++) s.insert(i);
    70. for(int i=1;i<=m;i++){
    71. int a,b;
    72. char c;
    73. cin>>c>>a>>b;
    74. if(c=='D')
    75. s.unionSet(a,b);
    76. else{
    77. if(s.find(a)!=s.find(b)) cout<<"Not sure yet.";
    78. else if(s.parent[a]==s.parent[b]) cout<<"In the same gang.";
    79. else cout<<"In different gangs.";
    80. cout<
    81. }
    82. }
    83. }
    84. return 0;
    85. }

      这是一道并查集的经典题目,希望大家掌握。 

    该题链接:

    OpenJudge - 3:发现它,抓住它http://dsalgo.openjudge.cn/retrieval/3/ 

  • 相关阅读:
    制造业质量管理如何实现数字化?
    Jenkins CVE-2017-1000353远程代码执行漏洞复现
    计算机毕业设计ssm达梦商城-跨平台多商户电商平台nc9f0系统+程序+源码+lw+远程部署
    kkfileview在docker部署后预览出现预览中的字体样式与源文件不同的解决办法
    信息化发展56
    线性代数学习笔记6-2:行列式的理解、行列式的性质
    柯桥学俄语|商务俄语двое型与оба (обе) 型集合数词用法攻略
    查看docker run 时启动命令
    CSS 两栏布局
    Linux下七种文件类型、文件属性及其查看方法
  • 原文地址:https://blog.csdn.net/wo_ai_luo_/article/details/127231733