我想创建一个具有传递对的集合。我的输入将是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 ++中实现这一点?
答案 0 :(得分:1)
你有一个图表,你想把它变成一个免费的类别,AKA是该图的传递闭包。
您的int
对元素是顶点,这些对本身就是边,这是您的图形。现在,图表上的免费类别是具有边缘合成法则的图表,以及可以由法律生成的所有其他边缘。法律说
f
从a
到b
g
到b
c
f∘g
的边缘,从a
到c
(f∘g)∘h = f∘(g∘h)
)(每个类别也有单位边缘,表示1
a
,每个顶点a
从a
到a
},以及一条法律,其中对于从f
到a
,b
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