有向グラフに含まれる閉路のうち、辺重みの平均が最小のものを求めます。 実装は Karp’s algorithm です。 以下では $n$ を頂点数、$m$ を辺数とします。
依存関係
umilib/header.hppumilib/graph/graph.hpp
使い方
#include "umilib/graph/min_mean_cycle.hpp"
min_mean_cycle
edges<S> min_mean_cycle(graph<S>& G)
$G$ に含まれる閉路のうち、辺重みの平均が最小のものを返します。
閉路が存在しない場合は空の edges<S> を返します。
アルゴリズム概要
仮想ソース(全頂点へコスト $0$ で接続)から「ちょうど $k$ 辺を使う最短距離」$d_k(v)$ を $k=0,\ldots,n$ について計算し、Karp の定理
\[\mu^* = \min_{v} \max_{0 \le k < n} \frac{d_n(v) - d_k(v)}{n - k}\]により最小平均 $\mu^*$ を求めます。 その後、親ポインタを $n$ 回たどった頂点列から鳩の巣原理により閉路を復元します。
制約
Gは有向グラフ- 辺重みは実数(負可)
計算量
- $O(mn)$
使用例
#include "umilib/graph/min_mean_cycle.hpp"
int main(){
graph<long long> G(4, true);
G.add_edge(0, 1, 3);
G.add_edge(1, 2, 1);
G.add_edge(2, 3, 2);
G.add_edge(3, 1, 0); // 1->2->3->1: mean = (1+2+0)/3
auto cycle = min_mean_cycle(G);
if(cycle.empty()){
// 閉路なし
} else {
double mean = 0;
for(auto e : cycle) mean += e.cost;
mean /= cycle.size();
cout << mean << '\n';
}
}