问题描述
我知道如何计算 Boost 中连通分量的总数,但是有没有一种有效的方法可以使用 boost 的图形库来计算最大连通分量的大小。
解决方法
我认为最有效的方法是用自定义类型替换 component map。
我创建了一个小的 WritePropertyMap 来做到这一点:
template <typename V>
struct Mapper {
using Id = int; // component id
using Cardinality = int;
using Map = boost::container::flat_map<Id,Cardinality>;
using Value = Map::value_type;
Map& storage;
friend void put(Mapper& m,V const& /*v*/,Id id) { m.storage[id] += 1; }
Value largest() const {
return not storage.empty()
? *max_element(begin(storage),end(storage),[](Value const& a,Value const& b) {
return a.second < b.second;
})
: Value{};
}
};
我们需要将我们的属性映射告诉 Boost:
template <typename V> struct boost::property_traits<Mapper<V>> {
using category = boost::writable_property_map_tag;
using key_type = V;
using value_type = int;
};
注意
存储和属性映射之间的分离是因为属性映射是按值传递的 - 并且复制起来应该很便宜。
现在我们可以使用它,稍微调整一下 library example:
Mapper<V>::Map result;
Mapper<V> mapper{result};
int num = connected_components(g,mapper);
auto [id,cardinality] = mapper.largest();
std::cout << "Largest component #" << id << " (out of " << num
<< " components) has " << cardinality << " vertices\n";
印刷品
Largest component #0 (out of 3 components) has 3 vertices
这符合预期的输出。
奖金
如果您有预期数量的组件,您可以使用 small_vector/static_vector 来优化存储,例如
using Value = std::pair<Id,Cardinality>;
using Map = boost::container::flat_map<
Id,Cardinality,std::less<>,boost::container::small_vector<Value,10>>;
这样,除非您有超过 10 个组件,否则您永远不会看到映射器存储的动态分配。