我正在使用C ++和Boost Graph Library(BGL)编写程序。 我有两个名为“建筑物和合同”的课程。我需要制作一个代表它们之间连接关系的图表。因此,图应具有两种类型的顶点(B和C),被定向并包括边B-> B,C-> C和B-> C.
修改
实际上,我试图避免不同类型节点之间的连接,所以我有两个单独的图。但是由于实际上实现了B和C之间的现有关系,它使我的模型变得更加复杂。边缘B1-> B2表明已经构建了B1来构建B2。 C1-> C2实际上是相同的,但就合同而言。 B-> C表示合同C可以在建筑物B中完成。
答案 0 :(得分:1)
我已经发表评论询问目标:
如果你能够描述你想要解决的问题,我会很乐意展示(几种)方法。因为在这一点上,你根本不清楚你需要集成数据结构(我无法想到可以从B-B,C-C,B-C边缘获益的算法)。在我的脑海中,2个单独的图形,一个隐含的图形与它们相结合,或者一个图形与可选的过滤视图相结合。过滤可以通过某种(动态)类型切换来完成,也可以使用某种外部/侵入索引来完成。 – sehe 31 mins ago
无论如何,您可以使用boost::variant
完全完成问题(即可能是X/Y problem个问题):
<强> Live On Wandbox 强>
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/property_map/function_property_map.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/variant.hpp>
#include <fstream>
using namespace boost;
namespace Nodes {
struct Building { std::string id; };
struct Contract { std::string id; };
static inline std::ostream& operator<<(std::ostream& os, Building const& b) { return os << "Building " << b.id; }
static inline std::ostream& operator<<(std::ostream& os, Contract const& b) { return os << "Contract " << b.id; }
std::string id_of(Building const& b) { return b.id; }
std::string id_of(Contract const& c) { return c.id; }
std::string shape_of(Building const& b) { return "circle"; }
std::string shape_of(Contract const& c) { return "diamond"; }
}
using Nodes::Building;
using Nodes::Contract;
using Vertex = boost::variant<Building, Contract>;
std::string id_of(Vertex const& v) {
return boost::apply_visitor([](auto const& node) { return id_of(node); }, v);
}
std::string shape_of(Vertex const& v) {
return boost::apply_visitor([](auto const& node) { return shape_of(node); }, v);
}
typedef adjacency_list<vecS, vecS, directedS, Vertex> Graph;
int main() {
Graph g;
auto office1 = add_vertex(Building{ "office1" }, g);
auto office2 = add_vertex(Building{ "office2" }, g);
auto warehouse1 = add_vertex(Building{ "warehouse1" }, g);
auto contract1 = add_vertex(Contract{ "contract1" }, g);
auto contract2 = add_vertex(Contract{ "contract2" }, g);
add_edge(office1, office2, g);
add_edge(warehouse1, contract1, g);
add_edge(contract2, contract1, g);
{
std::ofstream dot_file("graph.dot");
dynamic_properties dp;
dp.property("node_id", boost::make_transform_value_property_map(&::id_of, boost::get(boost::vertex_bundle, g)));
dp.property("shape", boost::make_transform_value_property_map(&::shape_of, boost::get(boost::vertex_bundle, g)));
dp.property("label", boost::make_transform_value_property_map(
[](Vertex const& v) { return boost::lexical_cast<std::string>(v); },
boost::get(boost::vertex_bundle, g)));
write_graphviz_dp(dot_file, g, dp);
}
print_graph(g);
}
打印
0 --> 1
1 -->
2 --> 3
3 -->
4 --> 3
除了为以下图表生成graph.dot
之外:
源.dot看起来像这样:
digraph G {
office1 [label="Building office1", shape=circle];
office2 [label="Building office2", shape=circle];
warehouse1 [label="Building warehouse1", shape=circle];
contract1 [label="Contract contract1", shape=diamond];
contract2 [label="Contract contract2", shape=diamond];
office1->office2 ;
warehouse1->contract1 ;
contract2->contract1 ;
}
在线渲染