zoukankan      html  css  js  c++  java
  • 算法训练--并查集

    /*
    给定n个变量和m个约束,判定是否能找出一种赋值方案满足这m个约束条件
    */
    //n:如题意
    //m:如题意
    //A:大小为m的数组,表示m条约束中的a
    //B:大小为m的数组,表示m条约束中的b
    //E:大小为m的数组,表示m条约束中的e
    /* 并查集解决 */
    const int N = 300005;
    //Father:每个节点的父亲节点
    //Rank:节点的秩
    int Father[N],Rank[N];

    //查找结点X所在的根
    //x:节点x
    int find(int x){
    if(Father[x] != x)
    return x;
    Father[x] = find(Father[x]);
    return Father[x];
    }

    string getAnswer(int n,int m,vector<int> A,vector<int> B,vector<int> E){
    //初始化
    for(int i = 0;i <= n; ++i){
    Father[i] = i;
    Rank[i] = 0;
    }
    int cnt = 0;
    for(int i=0;i < m; ++i){
    if(E[i] == 1){
    swap(A[i],A[cnt]);
    swap(B[i],B[cnt]);
    swap(E[i],E[cnt]);
    ++cnt;
    }
    }
    for(int i = 0;i < m; ++i){
    int setA = find(A[i]);//找到A[i]所在集合的根
    int setB = find(B[i]);//找到B[i]所在集合的根
    if(E[i] == 0){
    //如果setA == setB,说明A[i]和B[i]在同一棵树中,
    //而本身两者不应该存在关系,所以此时这种情况不存在
    if(setA == setB){
    return "No";
    }
    } else{//setA,setB 是一个数字
    //当A[i]和B[i]存在关系,并且两者所在的树的根不同时,说明两者分别属于
    //不同的树,此时是可以进行合并的;
    if(setA != setB){
    //合并的要求是判断两棵树的大小,原则上是小树作为大树的子树

    if(Rank[setA] > Rank[setB])
    //始终将小的放在setA中,大的放在setB中
    swap(setA,setB);
    //根据判断结果, 将setA归置在setB中
    Father[setA] = setB;
    //若setA,setB相同,则说明两者在同一棵树中,将setB的秩增加
    //其实我觉得在这应该就是setB所在的树的高度+1,因为
    if(Rank[setA] == Rank[setB])
    Rank[setB] += 1;
    }
    }
    }
    return "Yes";
    }

     并查集讲解:https://blog.csdn.net/dm_vincent/article/details/7655764

  • 相关阅读:
    回答提出的问题1-17章
    《构建之法》第13-17章读书笔记
    读《一个程序员的生命周期》有感
    构建之法的第十、十一、十二章读书笔记
    阅读《构建之法》第8,9,10章
    5.2-5.3
    作业5.1测试与封装
    读《构建之法》5.6.7 思考
    读《构建之法》的思考
    作业2 结对思则运算
  • 原文地址:https://www.cnblogs.com/drcm/p/9972218.html
Copyright © 2011-2022 走看看