2014-07-05 20 views
0

我想创建一个具有传递对的集合。我的输入将是pair<int, int>的形式,我需要一个具有给定输入的所有传递对的集合。例如,如果我有{1,2,2} {2,1} {2,3} {3,4}作为输入对,那么我需要一个具有{{1,2},{2} ,1},{1,3},{3,4},{1,4},{2,4}}。我还需要找出一个给定的对是否是这个传递集的成员。 是否有任何内置的数据结构/ STL库,这将允许我在C++中完成此操作?使用STL C++编写传递对集合

+1

使用[组](HTTP://en.cppreference。com/w/cpp/container/set)将是明显的答案 – IllusiveBrian

回答

1

你有一个图,你想把它变成一个自由的类别,也就是该图的传递闭包。

您的int对元素是顶点,对本身是边,这就是您的图。现在图中的一个自由类别是具有边缘组合定律的图形以及可由法则产生的所有附加边缘。法律规定,

  • 如果有一个边缘(或“箭头”的范畴论名字吧)fab
  • 以及从b运行到c
  • 边缘g运行再有就是表示f∘g另一边缘运行从ac
  • 组合物缔合((f∘g)∘h = f∘(g∘h)

(每个类别还单元的边缘,表示1aa运行a为每个顶点a,并且说,一个法律,对于每一个箭头fab运行,1a∘f = f∘1b= f,但我们不是在谈论那些)。

此答案的一般教育部分现已完成。

C++标准库中没有相关的算法,但您可能需要检查boost::graph或任何其他面向图形的库。 boost::graphtransitive_closure方法,这正是你想要的。

set<pair<int, int>> myset; 

传递闭包然后可以用计算:

1

你可以代表你的一套

void transitive_closure(set<pair<int, int>>& s) 
{ 
    set<pair<int, int>> a; // missing nodes to add 
    for (auto i = s.cbegin(); i != s.cend(); i++) 
    { 
     for (auto j = i; ++j != s.cend(); j) 
     { 
      if (i->second == j->first 
        && i->first != j->second 
        && s.count(make_pair(i->first, j->second))==0) 
       a.insert(make_pair(i->first, j->second)); 
     } 
    } 
    if (!a.empty()) { 
     for (auto p : a) 
      s.insert(p); 
     transitive_closure(s); 
    } 
} 

这不是最优化的算法,因为递归将重复一些比较。但它的工作。按照他的方式,我认为你已经在结果集中忘记了{2,3}。

要检查一对属于集合,只是检查是否s.count(make_pair(i->first, j->second)!=0

+0

我得到这个错误:'class std :: set >'没有名为'cbegin','cend',| ' - >'的基本操作数不是指针|另外{for(auto p:a)} < - 这也抛出了另一个错误。 – user3125772

+0

嗯......我用msvc2013编译和测试了它。你使用什么编译器? – Christophe

+0

@ user3125772'.cbegin()'和'.cend()'是C++ 11(http://www.cplusplus.com/reference/set/set/)。如果你使用gnu,不要忘记'-std = C++ 11'编译器选项。其他人可以使用'.begin()'和'.end()',它们的非常量等价。 – Christophe