Mais conteúdo relacionado Boost.GraphでJR全線乗り尽くしプランを立てる - プログラミング生放送+CLR/H+Sapporo.cpp 勉強会@札幌 (2014.7.12)13. ●
グラフ:状態(頂点 vertex, node)と、
二つの状態を結ぶもの(辺 edge)からなる
データ構造(今回は駅が頂点、路線が辺)
●
各辺には、通ることで加算される利益や
損失の数値(重み)を与えることができる
(今回は距離を重みとし損失とみなす)
桑園 札幌 苗穂 白石 平和
厚別八軒
琴似
22 16 22 36
4422
22
(辺の重みに書かれた
距離の単位は「0.1km」)
19. // 駅名をキー、頂点を値とする連想配列
std::map<std::string, RouteNetwork::vertex_descriptor> names2vertices;
while(!(ifs.eof())){
// (中略:ここで行を読み込む)
// s[0] と s[1] に地点名が、 distance に距離が入る
// 頂点を追加(まだ存在していないなら)
for(size_t i = 0; i <= 1; ++i){
it = names2vertices.find(s[i]);
if(it == names2vertices.end()){
vd[i] = boost::add_vertex(s[i], *this);
names2vertices.insert(std::make_pair(s[i], vd[i]));
}else{
vd[i] = it->second;
}
}
// 辺を追加
boost::add_edge(vd[0], vd[1], distance, *this);
total_distance += distance;
}
41. Boost.Graphだとこんな具合
// ---------- 変数宣言類は大幅に省略してます ----------
std::pair<vertex_iterator, vertex_iterator> vertex_range = boost::vertices(*this);
for(vertex_iterator itv = vertex_range.first; itv != vertex_range.second; ++itv){
if(out_degree(*itv, *this) == 2){ // 次数が2の頂点があったら
// 隣接する頂点と辺を覚えておき
std::pair<out_edge_iterator, out_edge_iterator> edge_range =
boost::out_edges(*itv, *this);
for(out_edge_iterator ite = edge_range.first;
ite != edge_range.second; ++ite, ++i){
sides[i] = vertex_target(*itv, *ite);
distance += boost::get(boost::edge_weight, *this, *ite);
links[i] = *ite;
}
// 元の辺を取り除くとともに新しく辺を加える
boost::add_edge(sides[0], sides[1], distance, *this);
boost::remove_edge(links[0], *this); boost::remove_edge(links[1], *this);
}
}
43. 白 岩 滝 旭 富 新 南 沼 追
白
岩
滝
旭
富
新
南
沼
追
この問題には「フロイド=ワーシャル法」と
いう有名なアルゴリズムがあって
Boost.Graphにも入っています
boost::floyd_warshall_all_pairs_shortest_paths(graph, result);
resultは「result[vertex1][vertex2] としたときに辺の重みが返る」
ものなら何でもよい。例えばstd::map< vertex_descriptor,
std::map<vertex_descriptor, int> > (辺の重みがintの場合)
沼ノ端
追分
新得南千歳
白石
滝川
旭川
富良野
岩見沢