找出不相交集的数量

时间:2015-06-17 21:56:18

标签: c++ algorithm data-structures disjoint-sets disjoint-union

对于那些不熟悉Disjoint-set数据结构的人。

https://en.wikipedia.org/wiki/Disjoint-set_data_structure

我正试图找到不。来自给定朋友和他们的关系的朋友群体。当然,毫无疑问,使用BFS / DFS可以很容易地实现这一点。但是我选择使用不相交的集合,我也倾向于找到这个人所属的朋友组等,并且不相交集合肯定听起来适合那种情况。

我已经实现了Disjoint集数据结构,现在我需要找到它包含的不相交集的数量(这将给出组的数量)。

现在,我一直在努力实现如何有效地找到不相交集的数量,因为朋友的数量可以大到1 00 00 0。

我认为应该有效的选项。

  1. 将新套装附在原稿背面,然后销毁旧套装。

  2. 在每个联盟中更改每个元素的父母。

  3. 但是由于朋友的人数很多,我不确定这是否是正确的方法,也许是否有其他有效的方式,或者我应该继续执行上述任何一种方法。

    这是我的代码以获取更多详细信息。(我在这里没有实现计数不相交集)

    //disjoint set concept 
    
    //https://www.topcoder.com/community/data-science/data-science-tutorials/disjoint-set-data-structures/
    // initially all the vertices are takes as single set and they are their own representative.
    // next we see, compare two vertices, if they have same parent(representative of the set), we leave it.
    // if they don't we merge them it one set.
    // finally we get different disjoint sets.
    
    #includes ...
    using namespace std;
    
    #define edge pair<int, int>
    const int max 1000000;
    vector<pair<int, edge > > graph, mst;
    int N, M;
    int parent[max];
    
    int findset(int x, int* parent){
     //find the set representative.
        if(x != parent[x]){ 
            parent[x] = findset(parent[x], parent);
        }
    
        return parent[x];
    }
    void disjoints(){
        for(int i=0; i<M; i++){
            int pu = findset(graph[i].second.first, parent);
            int pv = findset(graph[i].second.second, parent);
    
            if(pu != pv){ //if not in the same set.
                mst.push_back(graph[i]);
                total += graph[i].first;
                parent[pu] = parent[pv]; // create the link between these two sets
            }
        }
    }
     void noOfDisjoints(){
      //returns the No. of disjoint set.
     }
    void reset(){
        for(int i=0; i<N; i++){
            parent[i] = i;
        }
    }
    
    int main() {
                cin>>N>>M; // No. of friends and M edges
            int u,v,w;    // u= source, v= destination, w= weight(of no use here).  
            reset();
            for(int i =0; i<M ;i++){
                cin>>u>>v>>w;
                graph.push_back(pair<int, edge>(w,edge(u,v)));
            }
            disjoints();
            print();
        return 0;
    }
    

2 个答案:

答案 0 :(得分:5)

Disjoint Set Data Structure中两个项目a,b上的每个联合操作都有两种可能的情形:

  1. 您尝试将同一组中的项目联合起来。在这种情况下,什么也没做,并且不相交集的数量保持不变。
  2. 你将来自两个不同集的项联合起来,所以你基本上将两个集合合为一个 - 有效地减少了不相交集的数量。
  3. 由此,我们可以得出结论,通过从上面跟踪类型(2)的联合数量,很容易在每个时刻找到不相交集的数量。
    如果我们按succ_unions表示此数字,则每个点的集合总数为number_of_initial_sets - succ_unions

答案 1 :(得分:2)

如果您需要知道的是不相交集的而不是它们是什么,一个选项是将计数器变量添加到您的数据结构中,计算有多少不相交集。最初,它们有 n ,每个元素一个。每次执行并集操作时,如果两个元素没有相同的代表,那么您知道将两个不相交的集合合并为一个,因此可以减少计数器。这看起来像这样:

if (pu != pv){ //if not in the same set.
    numDisjointSets--;  // <--- Add thie line
    mst.push_back(graph[i]);
    total += graph[i].first;
    parent[pu] = parent[pv]; // create the link between these two sets
}

希望这有帮助!