使用STL C ++创建传递对集

时间:2014-07-05 18:03:04

标签: c++ stl set transitive-closure

我想创建一个具有传递对的集合。我的输入将是pair<int, int>形式,我需要一个具有给定输入的所有传递对的集合。 例如,如果我有{1,2} {2,1} {2,3} {3,4}对作为输入,那么我需要一个具有{{1,2},{2}对的SET 1},{1,3},{3,4},{1,4},{2,4}}。我还需要查找给定对是否是此传递集的成员。 是否有任何内置的数据结构/ STL库可以让我在C ++中实现这一点?

2 个答案:

答案 0 :(得分:1)

你有一个图表,你想把它变成一个免费的类别,AKA是该图的传递闭包。

您的int对元素是顶点,这些对本身就是边,这是您的图形。现在,图表上的免费类别是具有边缘合成法则的图表,以及可以由法律生成的所有其他边缘。法律说

  • 如果有边缘(或#34;箭头&#34;正如类别理论所指的那样)fab
  • 以及从gb
  • 的边c
  • 然后是另一条代表f∘g的边缘,从ac
  • 该作品是关联的((f∘g)∘h = f∘(g∘h)

(每个类别也有单位边缘,表示1 a ,每个顶点aaa },以及一条法律,其中对于从fab 1 {{}的每个箭头a 1}} ∘f = f∘1 b,但我们不是在谈论这些。)

特此完成本答复的一般教育部分。

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

答案 1 :(得分:1)

您可以使用以下代码表示您的设置:

set<pair<int, int>> myset;

然后可以使用以下公式计算传递闭包。

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