<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Eating Your Own Cat Food</title><link>https://miti-7.github.io/</link><description>Recent content on Eating Your Own Cat Food</description><generator>Hugo -- gohugo.io</generator><language>ja</language><lastBuildDate>Tue, 23 Dec 2025 00:01:00 +0900</lastBuildDate><atom:link href="https://miti-7.github.io/index.xml" rel="self" type="application/rss+xml"/><item><title>フロー等価木と Gusfield のアルゴリズム</title><link>https://miti-7.github.io/post/flow-equivalent-tree-gusfield/</link><pubDate>Tue, 23 Dec 2025 00:01:00 +0900</pubDate><guid>https://miti-7.github.io/post/flow-equivalent-tree-gusfield/</guid><description>&lt;img src="https://miti-7.github.io/post/flow-equivalent-tree-gusfield/images/example.png" alt="Featured image of post フロー等価木と Gusfield のアルゴリズム" /&gt;&lt;h2 id="はじめに"&gt;はじめに
&lt;/h2&gt;&lt;p&gt;この記事は&lt;a class="link" href="https://adventar.org/calendars/12007" target="_blank" rel="noopener"
&gt;木 Advent Calendar 2025&lt;/a&gt; の 23 日目の記事です．&lt;br&gt;
この記事では無向グラフのすべての頂点対の最大流の情報を持つ木であるフロー等価木を紹介します．&lt;br&gt;
まず，フロー等価木の説明をします．次に，フロー等価木を構築するアルゴリズムの説明とその証明を行います．最後にフロー等価木を実装し，例として競プロの問題を解きます．&lt;/p&gt;
&lt;p&gt;無向グラフや最小カットなどの用語については&lt;a class="link" href="https://miti-7.github.io/post/gomory-hu-tree/" target="_blank" rel="noopener"
&gt;Gomory-Hu 木&lt;/a&gt;を参照してください．&lt;/p&gt;
&lt;h2 id="フロー等価木"&gt;フロー等価木
&lt;/h2&gt;&lt;p&gt;同じ頂点集合 $V$ をもつ $2$ つの重み付き無向グラフ $G(V, E)$ と $H(V, F)$ を考えます．ただし，$F \subset E$ とは限りません．&lt;br&gt;
$G$ と $H$ の s - t 間の最大流の値をそれぞれ $f_{s, t; G}$，$f_{s, t; H}$ と表記します&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;．&lt;br&gt;
任意の $2$ 頂点 $s, t \in V$ に対し $f_{s, t; H} = f_{s, t;G}$ が成り立つとき，$H$ は $G$ にフロー等価（flow equivalent）であるといいます．&lt;br&gt;
特に，木 $T$ がグラフ $G$ にフロー等価であるとき，$T$ をフロー等価木（flow equivalent tree）とよびます．&lt;/p&gt;
&lt;p&gt;フロー等価木と似た概念に Gomory-Hu 木があります&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;．&lt;br&gt;
Gomory-Hu 木は，$G$ の任意の $2$ 頂点 $s, t \in V$ に対し，木の最小 s - t カット $S$ が $G$ の最小 s - t カットとなるような木です&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;．&lt;br&gt;
Gomory-Hu 木は常にフロー等価木ですが，フロー等価木であっても Gomory-Hu 木でない場合があります．&lt;/p&gt;
&lt;p&gt;下の図はグラフ $G$ とそれに対応するフロー等価木 $T$ です．
各 s - t 間の最大流の値は $G$ と $T$ で一致します．&lt;br&gt;
一方，$T$ の最小 1-3 カットは $\{1, 2, 4\}$ なのに対し，$G$ のカット $\{1, 2, 4\}$ の容量は $11$ となり，一致しない最小 s - t カットが存在することがわかります．&lt;/p&gt;
&lt;div style="display: flex; gap: 20px;"&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$s, t$&lt;/th&gt;
&lt;th&gt;$G$ の s - t 間の最大流の値&lt;/th&gt;
&lt;th&gt;$T$ の s - t 間の最大流の値&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$1, 2$&lt;/td&gt;
&lt;td&gt;$6$&lt;/td&gt;
&lt;td&gt;$6$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$1, 3$&lt;/td&gt;
&lt;td&gt;$9$&lt;/td&gt;
&lt;td&gt;$9$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$1, 4$&lt;/td&gt;
&lt;td&gt;$6$&lt;/td&gt;
&lt;td&gt;$6$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$2, 3$&lt;/td&gt;
&lt;td&gt;$6$&lt;/td&gt;
&lt;td&gt;$6$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$2, 4$&lt;/td&gt;
&lt;td&gt;$12$&lt;/td&gt;
&lt;td&gt;$12$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$3, 4$&lt;/td&gt;
&lt;td&gt;$6$&lt;/td&gt;
&lt;td&gt;$6$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img src="images/example.png" width="70%"&gt;
&lt;h2 id="フロー等価木を構築するアルゴリズム"&gt;フロー等価木を構築するアルゴリズム
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;変数と関数&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$n$: $G$ の頂点の数&lt;/li&gt;
&lt;li&gt;$p[i]$: 頂点 $i$ の親の頂点&lt;/li&gt;
&lt;li&gt;$fl[i]$: 辺 $(i, p[i])$ の重み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;step1: 初期化&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;各頂点 $s$ について $p[s] \coloneqq 1$&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;step2: $2$ から $n$ の頂点 $s$ について以下を行う&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;$t \coloneqq p[s]$&lt;/li&gt;
&lt;li&gt;$G$ 上で最小 s - t カット $X$ を求める．$s \in X$ とする&lt;/li&gt;
&lt;li&gt;$fl[s] \coloneqq f_{s, t; G}$&lt;/li&gt;
&lt;li&gt;$s + 1$ から $n$ の頂点 $i$ について以下を行う
&lt;ul&gt;
&lt;li&gt;$i \in X$ かつ $p[i] = t$ なら $p[i] \coloneqq s$ とする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="準備"&gt;準備
&lt;/h2&gt;&lt;p&gt;アルゴリズムがフロー等価木を構築する証明をする前にいくつかの補題を導入します．&lt;/p&gt;
&lt;h3 id="補題-1"&gt;補題 1
&lt;/h3&gt;&lt;p&gt;$(X, Y)$ を $x \in X, y \in Y$ であるような最小 x - y カットとする．$u, v \in X$ であるような任意の最小 u - v カットを $(U, V)$ とする．$y \in U$ のとき，$(U^{\prime}, V^{\prime}) = (U \cup Y, V \cap X)$ は最小 u - v カットとなり，$y \in V$ のとき，$(U^{\prime}, V^{\prime}) = (U \cap X, V \cup Y)$ は最小 u - v カットとなる．&lt;/p&gt;
&lt;h3 id="系-1"&gt;系 1
&lt;/h3&gt;&lt;p&gt;$(X, Y), (U, V), (U^{\prime}, V^{\prime})$ を補題 1 と同様にとる．最小 u - v カット $(U^{\prime}, V^{\prime})$ は $(X, Y)$ と交差せず，$X$ を $(U, V)$ と同様に分割する&lt;/p&gt;
&lt;h3 id="補題-2"&gt;補題 2
&lt;/h3&gt;&lt;p&gt;長さ $k \ge 2$ の互いに異なる頂点列 $v_1, v_2, v_3, \cdots, v_k$ について，$f_{v_1, v_k} \ge \min \limits_{1 \le i \le k - 1} f_{v_i, v_{i + 1}}$ が成り立つ&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://miti-7.github.io/post/gomory-hu-tree/#%E8%A3%9C%E9%A1%8C-1" target="_blank" rel="noopener"
&gt;Gomory-Hu 木の補題 1&lt;/a&gt;を参照してください．&lt;/p&gt;
&lt;h3 id="系-2"&gt;系 2
&lt;/h3&gt;&lt;p&gt;$G$ の $3$ つの頂点 $i, j, k$ について，$f_{i, j}, f_{i, k}, f_{j, k}$ のうち少なくとも $2$ つは最小値である&lt;/p&gt;
&lt;p&gt;系 2 を示します．&lt;br&gt;
補題 2 により，$i, j, k$ に対して，$f_{i, k} \ge \min(f_{i, j}, f_{j, k})$ が成立します．&lt;br&gt;
$f_{i, j}, f_{i,k}, f_{j,k}$ のうち，$1$ つだけが最小値であると仮定し，矛盾を導きます．&lt;br&gt;
$f_{i, k}$ が唯一の最小値だとします．すると，$f_{i, k} \lt \min(f_{i, j}, f_{j, k})$ となり，矛盾します．&lt;br&gt;
$f_{i, j}, f_{j, k}$ についても同様に示せるため，系 2 が示せました．&lt;/p&gt;
&lt;h3 id="補題-3"&gt;補題 3
&lt;/h3&gt;&lt;p&gt;アルゴリズムによって構築される最終的な $T$ で，ある頂点 $i$ からある頂点 $j$ へ向かう有向パス $P_{i, j}$ があるとする．さらに，$j$ に入る有向辺 $(k, j)$ があって，$k$ は $P_{i, j}$ 上の $j$ 以外のどの頂点よりも頂点番号が小さいとする．このとき以下が成立する．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アルゴリズムが最小 k - j カット $C$ を計算したとき，（構築途中の）$T$ 上で $i$ は $j$ の隣接頂点だった&lt;/li&gt;
&lt;li&gt;「最小カット $C$ において $i$ が $k$ 側にいる」と「最終的な $T$ で $k$ がパス $P_{i, j}$ 上にいる」は同値&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="アルゴリズムの証明"&gt;アルゴリズムの証明
&lt;/h2&gt;&lt;p&gt;アルゴリズムが最終的に構築した木を $T$ とします．&lt;br&gt;
アルゴリズムは木の各辺 $(x, y)$ の重みを $f_{x, y}$ としているので，木の辺 $(x, y)$ となるような頂点 $x, y$ について $G$ の x - y 間の最大流の値と $T$ の x - y 間の最大流の値は一致します．&lt;br&gt;
任意の頂点対 $(x, y)$ についても，$G$ 上の最大流の値 $f_{x, y}$ と $T$ 上の x - y パスの辺のうち重みが最小の辺の重みが一致することを示します．&lt;br&gt;
これは，x - y パスを $P_{x,y}$，x - y パスの辺の重みの集合を $P[x, y]$ と表記することにすると，$f_{x, y} = \min(P[x, y])$ を示すと言い換えることができます．&lt;br&gt;
$f_{x, y} \ge \min(P[x, y])$ と $f_{x, y} \le \min(P[x, y])$ をそれぞれ示します．&lt;/p&gt;
&lt;h3 id=""&gt;$f_{x, y} \ge \min(P[x, y])$
&lt;/h3&gt;&lt;p&gt;$T$ の x - y パスの頂点列 $x = v_1, v_2, \cdots, v_k = y$ を考えます．&lt;br&gt;
補題 2 から $f_{x, y} \ge \min \limits_{1 \le i \le k - 1} f_{v_i, v_{i+1}}$ が成り立ちます．&lt;br&gt;
アルゴリズムは木の各辺 $(v_i, v_{i + 1})$ の重みを $f_{v_i, v_{i + 1}}$ としているので，$\min \limits_{1 \le i \le k - 1} f_{v_i, v_{i+1}} = \min(P[x, y])$ となります．&lt;br&gt;
よって，$f_{x, y} \ge \min(P[x, y])$ が示せました．&lt;/p&gt;
&lt;h3 id=""&gt;$f_{x, y} \le \min(P[x, y])$
&lt;/h3&gt;&lt;p&gt;背理法で示します．&lt;br&gt;
$f_{x, y} \gt \min(P[x, y])$ となるような頂点対 $(x, y)$ があると仮定して矛盾を導きます．&lt;br&gt;
まず，この不等式を満たす頂点対の中から「$T$ 上の x - y パスの辺数が最も短い」パスを $1$ つ選び $P$ とします．この仮定とさきほど証明した「$f_{x, y} \ge \min(P[x, y])$」から，$P$ より短いパス $P_{a,b}$ については $f_{a, b} = \min(P[a, b])$ が成り立つことに注意します．&lt;/p&gt;
&lt;p&gt;アルゴリズムで作られる辺 $(s, t)$ を $s$ から $t$ への有向辺とみなします．すると，すべての辺は番号の大きい頂点から小さい頂点へ向くので，$T$ は有向木になります．&lt;br&gt;
このとき，パス $P$ が直線のときと V 字のときのそれぞれの場合について矛盾が生じることを示します．&lt;/p&gt;
&lt;h4 id="case1-パス--が直線のとき"&gt;Case1: パス $P$ が直線のとき
&lt;/h4&gt;&lt;p&gt;パス $P$ が $x \rightarrow \cdots \rightarrow v \rightarrow y$ のように，すべて同じ向きの有向パスになっている場合を考えます．&lt;/p&gt;
&lt;img src="images/case1.png" width="20%"&gt;
&lt;p&gt;まず，$\min(P[x, y]) = f_{x, v} = f_{v, y}$ を示します．&lt;br&gt;
パス $P$ は $P_{x, y} = P_{x, v} + (v, y)$ という形であるため，パス上の最小重みは
&lt;/p&gt;
$$\min(P[x, y]) = \min(\min(P[x, v]), f_{v, y})$$&lt;p&gt;
と表わせます．&lt;br&gt;
また，$P_{x, v}$ は $P$ より短いため $\min(P[x, v]) = f_{x, v}$ といえ，これを代入することにより
&lt;/p&gt;
$$\min(P[x, y]) = \min(f_{x, v}, f_{v, y})$$&lt;p&gt;
を得ます．&lt;br&gt;
$3$ つの頂点 $x, v, y$ を考えたとき，系 2 より $f_{x, v}, f_{v, y}, f_{x, y}$ のうち少なくとも最小値が 2 つあるといえますが，背理法の仮定により $f_{x, y} \gt \min(P[x, y])$ であるため，$f_{x, y}$ が最小値であることはありえません．&lt;br&gt;
よって，$\min(P[x, y]) = f_{x, v} = f_{v, y}$ が示せました．&lt;/p&gt;
&lt;p&gt;$T$ の辺 $(v, y)$ を作ったとき，アルゴリズムは最小 v - y カットを計算しています．&lt;br&gt;
ここで補題 3 を $i = x, j = y, k = v$ と対応させると，このカットは x - y カットでもあるため
&lt;/p&gt;
$$f_{x, y} \le f_{v, y} = \min(P[x, y])$$&lt;p&gt;
となります．&lt;br&gt;
これは，$f_{x, y} \gt \min(P[x, y])$ というような頂点対 $(x, y)$ があるという仮定と矛盾します．&lt;/p&gt;
&lt;h4 id="case2-パス--が-v-字のとき"&gt;Case2: パス $P$ が V 字のとき
&lt;/h4&gt;&lt;p&gt;パス $P$ が $x \rightarrow \cdots \rightarrow x_1 \rightarrow z \leftarrow y_1 \leftarrow \cdots y$ のように，$z$ で折り返す形になっている場合を考えます．頂点番号について $x_1 \lt y_1$ を仮定し，$y_1$ - $z$ カットを計算する前に $x_1$ - z カットが計算されたとします．&lt;/p&gt;
&lt;img src="images/case2-1.png" width="20%"&gt;
&lt;p&gt;まず，$m = \min(P[x, y])$ としたとき，$f_{x, z} = f_{y, z} = m$ となることを示します．&lt;br&gt;
$P$ が最短という仮定から，$f_{x,z} = \min(P[x, z])$，$f_{y,z} = \min(P[y, z])$ を得ます．&lt;br&gt;
$P[x, y]$ の最小重み $m$ は 2 つの部分パスの最小値の最小なので以下が成り立ちます．&lt;/p&gt;
$$
\begin{alignedat}{2}
m &amp;= \min(P[x, y]) \\
&amp;= \min(\min(P[x, z]), \min(P[y, z])) \\
&amp;= \min(f_{x, z}, f_{y, z}) \\
\end{alignedat}
$$&lt;p&gt;系 2 によると $f_{x,z}, f_{x, y}, f_{z, y}$ のうち，少なくとも $2$ つが最小値です．&lt;br&gt;
いま，背理法の仮定により頂点対 $(x, y)$ は $f_{x, y} \gt \min(P[x, y]) = m$ です．&lt;br&gt;
よって，$f_{x, z} = f_{y, z} = m$ が示せました．&lt;/p&gt;
&lt;p&gt;x - z パスの中で，重みが $m$ かつ $z$ に最も近い辺を $(u, v)$ とし，$v$ が $z$ 側の頂点とします．&lt;/p&gt;
&lt;img src="images/case2-2.png" width="20%"&gt;
&lt;p&gt;アルゴリズムがグラフ $G$ 上で最小 $x_1$ - z カット $(X_1, Z)$ と最小 u - v カット $(U, V)$ を作ったときを考えます．&lt;br&gt;
補題 3 によって以下がいえます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最小 $x_1$ - z カットでは，$x, u, v \in X_1$，$y, z \in Z$ となる&lt;/li&gt;
&lt;li&gt;最小 u - v カットでは，$x, y, u \in U$，$v \in V$ となる．$z$ が $U$ と $V$ のどちらに入るかは定まらない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ここで，補題 1 を使い最小 $x_1$ - z カットに交差しない u - v カット $C^{\star}$ を作ります．&lt;br&gt;
このとき，$z \in U$ の場合には，$C^{\star} = (U \cup Z, V \cap X_1)$ ととります．&lt;br&gt;
$z \in V$ の場合には，$C^{\star} = (U \cap X_1, V \cup Z)$ ととります．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;$z \in U$ のとき，$C^{\star}$ は $v$ と $z$ を分割します&lt;br&gt;
この場合，$C^{\star}$ は容量 $m$ で $v$ と $z$ を分けるカットであるため，$f_{v, z} \le m = \min(P[x, y])$ となります．&lt;br&gt;
$P_{v, z}$ は $P$ より短いため $f_{v, z} = \min(P[v, z])$ となります．&lt;br&gt;
これは，$m$ 以下の重みをもつ辺が $z$ よりに存在することになり矛盾します．&lt;/li&gt;
&lt;li&gt;$z \in V$ のとき，$C^{\star}$ は $x$ と $y$ を分割します&lt;br&gt;
この場合，$C^{\star}$ は容量 $m$ で $x$ と $y$ を分けるカットであるため，$f_{x, y} \le m = \min(P[x, y])$ となります．これは背理法の仮定に矛盾します．&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="問題"&gt;問題
&lt;/h2&gt;&lt;p&gt;例として&lt;a class="link" href="https://atcoder.jp/contests/pakencamp-2024-day1/tasks/pakencamp_2024_day1_r" target="_blank" rel="noopener"
&gt;パ研合宿 2024 第 1 日「SpeedRun」R - Maximum Water Flow&lt;/a&gt;を解きます．&lt;/p&gt;
&lt;p&gt;問題概要&lt;br&gt;
$N$ 頂点 $M$ 辺の容量付き無向連結グラフが与えられる．任意の異なる頂点 $i, j$ について，最大流の値を $f(i, j)$ とする．&lt;br&gt;
$(1, 2, \cdots, N)$ の順列 $P = (P_1, P_2, \cdots, P_N)$ のうち，すべての $1$ 以上 $N$ 以下の整数について $P_i \ne i$ を満たすものについて $\sum_{i = 1}^{N} f(i, P_i)$ の最大値を求めよ．&lt;/p&gt;
&lt;p&gt;解法&lt;br&gt;
$\text{cost}[i][j]$ を $i$ から $j$ への最大流の値とします．$N \le 100$ なので $N \times N$ 行の行列 cost を作ることができます．&lt;br&gt;
今回はフロー等価木の木構造は不要なので，cost 行列を直接構築します．cost 行列がつくれればハンガリアン法を使うことで割当の最大値が求まります．&lt;br&gt;
コードの主要な部分を解説します．記事や問題概要は one-based だったのに対し，コードは zero-based であることに注意してください．&lt;br&gt;
$5$ 行目で，s - t 間の最大流をもとめ，$6$ 行目で s - t 最小カットを求めています．&lt;br&gt;
$13$ 行目は $s$ とその親 $t$ の最大流の値をそのまま表に書くだけです．&lt;br&gt;
$14 - 18$ 行目では $s$ と $i \lt s$ となる頂点の最大流の値を設定します．&lt;br&gt;
頂点番号が $s$ 以下の頂点はすでに木の位置が決まっているため，s - i パスの最小重みとすることができます．&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dinic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;cut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dinic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimum_cut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;cut&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dinic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://atcoder.jp/contests/pakencamp-2024-day1/submissions/71715567" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://dl.acm.org/doi/abs/10.1137/0219009" target="_blank" rel="noopener"
&gt;Very simple methods for all pairs network flow analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.asakura.co.jp/detail.php?book_code=11780" target="_blank" rel="noopener"
&gt;基礎数理講座 5 グラフ理論&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.maruzen-publishing.co.jp/book/b10122539.html" target="_blank" rel="noopener"
&gt;ネットワークフローアルゴリズム&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;文脈からグラフが明らかなときは，$f_{s, t}$ と表記します&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Gomory-Hu 木は cut equivalent tree ともよばれます&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;詳しくは&lt;a class="link" href="https://miti-7.github.io/post/gomory-hu-tree/#gomory-hu-%e6%9c%a8" target="_blank" rel="noopener"
&gt;Gomory-Hu 木&lt;/a&gt;を参照してください&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Gomory-Hu 木</title><link>https://miti-7.github.io/post/gomory-hu-tree/</link><pubDate>Tue, 23 Dec 2025 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/gomory-hu-tree/</guid><description>&lt;img src="https://miti-7.github.io/post/gomory-hu-tree/images/t4.png" alt="Featured image of post Gomory-Hu 木" /&gt;&lt;h2 id="はじめに"&gt;はじめに
&lt;/h2&gt;&lt;p&gt;この記事は&lt;a class="link" href="https://qiita.com/advent-calendar/2025/mathematical-optimization" target="_blank" rel="noopener"
&gt;数理最適化 Advent Calendar 2025&lt;/a&gt; の 23 日目の記事です．&lt;br&gt;
この記事では Gomory-Hu 木を紹介します．Gomory-Hu 木とは無向グラフのすべての頂点対の最小カットの情報を持つ木のことです．&lt;br&gt;
まず，無向グラフの s - t カットを紹介し，カット関数が対称劣モジュラ関数であることを示します．次に，Gomory-Hu 木の定義といくつかの補題を示します．最後に Gomory-Hu 木を構築するアルゴリズムの説明とその証明を行います．&lt;br&gt;
実装は今回紹介するアルゴリズムより Gusfield によって提案されたアルゴリズムの方が簡単です．こちらについては別の記事で扱います．&lt;/p&gt;
&lt;h2 id="無向グラフの-s---t-カット"&gt;無向グラフの s - t カット
&lt;/h2&gt;&lt;p&gt;頂点集合 $V$ と無向辺 $E$ からなる無向グラフ $G(V, E)$ が与えられます．辺 $(u, v)$ には容量 $c_{uv} \ge 0$ が定まっているものとします．&lt;br&gt;
任意の頂点集合 $S \subseteq V$ に対し，辺の一方の端点のみが $S$ に属する辺集合を $\delta(S)$ とします．&lt;br&gt;
このときカット関数を以下のように定義し，この値をカットの容量と呼びます．&lt;/p&gt;
$$c(S) = \sum_{(u, v) \in \delta(S)} c_{uv}$$&lt;p&gt;ただし，$\emptyset \subsetneq S \subsetneq V$ を満たす頂点集合 $S$ をカットと呼ぶことにします．
今回は無向グラフを扱っているため $c(S) = c(V \setminus S)$ が成り立ちます．&lt;br&gt;
また，2 つの異なる頂点 $s$ と $t$ について $|S \cap \{s, t\}| = 1$ となるカット $S$ を s - t カットと呼びます．そのうち容量が最小のものを最小 s - t カットと呼び，その容量を $\lambda_{s, t}$ で表します．&lt;/p&gt;
&lt;p&gt;下のグラフを例に，$s$ に $1$，$t$ に $6$ を選んだときの s - t カットをいくつか見ていきます．&lt;/p&gt;
&lt;img src="images/s-t-cut_sample1.png" width="35%"&gt;
&lt;hr&gt;
&lt;p&gt;$S = \{1, 2, 3 \}$ は s - t カットのうちの 1 つです．
$S$ に属する頂点を赤，$V \setminus S$ に属する頂点を青で示します．&lt;br&gt;
辺の一方の端点のみが $S$ に属する辺は $(2, 4)$ と $(3, 5)$ です．よって，このカットの容量は $4 + 6 = 10$ となります．&lt;/p&gt;
&lt;img src="images/s-t-cut_sample2.png" width="35%"&gt;
&lt;hr&gt;
&lt;p&gt;$S = \{1, 3, 4 \}$ も s - t カットです．&lt;br&gt;
このカットの容量は $2 + 2 + 6 + 4 + 7 + 9 = 30$ となります．&lt;/p&gt;
&lt;img src="images/s-t-cut_sample3.png" width="35%"&gt;
&lt;hr&gt;
&lt;p&gt;$S = \{1 \}$ も s - t カットです．&lt;br&gt;
このカットの容量は $2 + 5 = 7$ となります．&lt;br&gt;
$s$ に $1$，$t$ に $6$ を選んだとき $7$ より容量の小さい s - t カットは存在しないためこのカットは最小 s - t カットです．&lt;/p&gt;
&lt;img src="images/s-t-cut_sample4.png" width="35%"&gt;
&lt;h2 id="カット関数の劣モジュラ性"&gt;カット関数の劣モジュラ性
&lt;/h2&gt;&lt;p&gt;関数 $f: 2^V \rightarrow \mathbb R$ は，任意の $A, B \subseteq V$ で以下の不等式が成立するとき劣モジュラであると呼ばれます．
&lt;/p&gt;
$$f(A) + f(B) \ge f(A \cap B) + f(A \cup B)$$&lt;p&gt;また，関数 $f$ は任意の $S \subseteq V$ について $f(S) = f(V \setminus S)$ が成り立つとき対称であると呼ばれます．&lt;br&gt;
対称で劣モジュラな関数は対称劣モジュラ関数と呼ばれます．&lt;/p&gt;
&lt;p&gt;無向グラフのカット関数 $c(S)$ が対称劣モジュラ関数であることを示します．&lt;br&gt;
頂点集合 $V$ を $V_1 = A \setminus B, V_2 = B \setminus A, V_3 = A \cap B, V_4 = V \setminus (A \cup B)$ の $4$ つに分割します．&lt;/p&gt;
&lt;img src="images/submodular.png" width="35%"&gt;
&lt;p&gt;辺の $2$ つの端点がそれぞれ $V_a$，$V_b$ に属する辺集合の容量の和を $\mathrm{cap}(a, b)$ とします．今回は無向辺を扱っているため $\mathrm{cap}(a, b) = \mathrm{cap}(b, a)$ となります．&lt;br&gt;
このとき，以下の式が成り立ちます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$c(A) = \mathrm{cap}(3, 4) + \mathrm{cap}(3, 2) + \mathrm{cap}(1, 4) + \mathrm{cap}(1, 2)$&lt;/li&gt;
&lt;li&gt;$c(B) = \mathrm{cap}(3, 4) + \mathrm{cap}(3, 1) + \mathrm{cap}(2, 4) + \mathrm{cap}(2, 1)$&lt;/li&gt;
&lt;li&gt;$c(A \cup B) = \mathrm{cap}(3, 4) + \mathrm{cap}(1, 4) + \mathrm{cap}(2, 4)$&lt;/li&gt;
&lt;li&gt;$c(A \cap B) = \mathrm{cap}(3, 1) + \mathrm{cap}(3, 2) + \mathrm{cap}(3, 4)$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらを整理すると&lt;/p&gt;
$$c(A) + c(B) - c(A \cup B) - c(A \cap B) = \mathrm{cap}(1, 2) + \mathrm{cap}(2, 1) = 2\mathrm{cap}(1, 2) \ge 0$$&lt;p&gt;となり，関数 $c(S)$ は劣モジュラ関数であることがわかります．&lt;br&gt;
また，関数 $c(S)$ は $c(S) = c(V \setminus S)$ が成り立つため対称です．&lt;br&gt;
以上により，無向グラフのカット関数が対称劣モジュラ関数であることが示せました．&lt;/p&gt;
&lt;h2 id="gomory-hu-木"&gt;Gomory-Hu 木
&lt;/h2&gt;&lt;p&gt;木から辺 $(u, v)$ を取り除いたときにできる $u$ を含む連結成分の頂点集合を $C_{uv}$ とします．&lt;br&gt;
Gomory-Hu 木は以下のように定義されます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;無向グラフ $G(V, E)$ の Gomory-Hu 木 $T(V, F)$ は，木のすべての辺 $(u, v) \in F$ について，$C_{uv}$ が $G$ の最小 u - v カットとなるような木である．つまり，$c(C_{uv}) = \lambda_{u, v}$ となる&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;．&lt;/li&gt;
&lt;li&gt;各辺 $(u, v) \in F$ の重みを $w(u, v)$ とすると，$w(u, v) = \lambda_{u, v}$ が成り立つ．&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gomory-Hu 木の定義では，木の辺となるような頂点対が $G$ の最小カットとなることのみを要求しています．&lt;br&gt;
あとで示しますが，この定義は任意の頂点対に拡張することができ，結果として Gomory-Hu 木は次の性質を持つといえます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$V$ 上の全域木 $T(V, F)$ である（ただし，$F \subseteq E$ とは限らない）．&lt;/li&gt;
&lt;li&gt;任意の異なる $2$ 頂点 $s, t \in V$ について，$T$ 上の最小 s - t カットは $G$ 上の最小 s - t カットとなり，その容量は一致する．&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下の図を例に Gomory-Hu 木の性質を確認します．&lt;/p&gt;
&lt;img src="images/gomory-hu_sample1.png" width="70%"&gt;
&lt;ul&gt;
&lt;li&gt;グラフの頂点 $1$ と頂点 $6$ の最小カットは $\{1\}$ でその容量は $7$ です．一方，木の頂点 $1$ と頂点 $6$ の最小カットは $\{1\}$ でその容量は $7$ です．&lt;/li&gt;
&lt;li&gt;グラフの頂点 $3$ と頂点 $5$ の最小カットは $\{1, 3\}$ でその容量は $10$ です．一方，木の頂点 $3$ と頂点 $5$ の最小カットは $\{1, 3\}$ でその容量は $10$ です．&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このように，任意の異なる 2 頂点 $s$，$t$ について，木の最小 s - t カットはグラフの最小 s - t カットになり，その容量は一致します．&lt;br&gt;
木の最小 s - t カットは，頂点 $s$ から頂点 $t$ へのパスのうち最も重みの小さい辺 $e$ を削除したときの一方の連結成分となり，カットの容量は辺 $e$ の重みとなるため簡単に求めることができます．&lt;/p&gt;
&lt;p&gt;Gomory-Hu 木は $n - 1$ 回の最小 s - t カット計算で求めることができます．&lt;br&gt;
Gomory-Hu のアルゴリズムを紹介する前に，準備としていくつかの補題を導入し，Gomory-Hu 木の性質が定義から導けることを示します．&lt;/p&gt;
&lt;h3 id="補題-1"&gt;補題 1
&lt;/h3&gt;&lt;p&gt;長さ $k \ge 2$ の互いに異なる頂点列 $v_1, v_2, v_3, \cdots, v_k$ について，$\lambda_{v_1, v_k} \ge \min \limits_{1 \le i \le k - 1} \lambda_{v_i, v_{i + 1}}$ が成り立つ．&lt;/p&gt;
&lt;p&gt;補題 1 を示します．&lt;br&gt;
$U$ を最小 $v_1$ - $v_k$ カットとし，$v_1 \in U$，$v_k \notin U$ とします．&lt;br&gt;
このとき，頂点列のどこかに $v_i \in U$，$v_{i + 1} \notin U$ であるような $i$ が存在します．&lt;/p&gt;
&lt;p&gt;直観的には，次のように考えることができます．&lt;br&gt;
$U$ に属する頂点を $\circ$，属さない頂点を $\times$，不明な頂点を $?$ とします．&lt;br&gt;
このとき，頂点列の所属は $(\circ, ?, ?, \cdots, ?, \times)$ と表せますが，$?$ がどのように決められようとどこかに $\circ, \times$ というペアが現れます．これは，$v_i \in U$，$v_{i + 1} \notin U$ であるような $i$ が存在しているということです．&lt;/p&gt;
&lt;p&gt;よって，$U$ は $v_i$ - $v_{i+1}$ カットでもあります．ただし，$U$ は最小 $v_i$ - $v_{i+1}$ カットとは限らないため，$\lambda_{v_i, v_{i + 1}} \le c(U) = \lambda_{v_1, v_k}$ となります．&lt;br&gt;
以上により，$\lambda_{v_1, v_k} \ge \min_{1 \le i \le k - 1} \lambda_{v_i, v_{i + 1}}$ が示せました．&lt;/p&gt;
&lt;h3 id="補題-2"&gt;補題 2
&lt;/h3&gt;&lt;p&gt;$s, t \in V$ を異なる 2 頂点とし，最小 s - t カットを $A$ とする．任意の異なる 2 頂点 $u, v \notin A$ について，$A \subseteq B$ か $A \cap B = \emptyset$ となるような最小 u - v カット $B$ が存在する．&lt;/p&gt;
&lt;img src="images/lemma2.png" width="45%"&gt;
&lt;p&gt;この補題は，すでに存在する最小 s - t カット $A$ と交差しないように最小 u - v カット $B$ をとることができることを意味します．図は $A \subseteq B$ の場合を表しています．&lt;/p&gt;
&lt;p&gt;補題 2 を示します．&lt;br&gt;
最小 s - t カットを $A$，最小 u - v カットを $B$ とします．$A \subseteq B$ か $A \cap B = \emptyset$ の場合は補題が成立しているので，$A \nsubseteq B$ かつ $A \cap B \ne \emptyset$ を仮定します．
$s \in A$，$s, u \in B$ であるとします&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;．&lt;br&gt;
このとき，$A \cup B$ が最小 u - v カットとなることを示します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$A \cup B$ は u - v カット&lt;br&gt;
$u \in B$ であるため $u \in A \cup B$ であり，$v \notin A$ かつ $v \notin B$ であるため $v \notin A \cup B$ です．&lt;br&gt;
よってこのカットは u - v カットです．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$c(A \cup B) = c(B)$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$c(A \cup B) \le c(B)$&lt;br&gt;
仮定より，$s \in A \cap B$，$t \notin A \cap B$ であるため，$A \cap B$ は s - t カットです．&lt;br&gt;
$A$ は最小 s - t カットで $A \cap B$ も s - t カットであるため，$c(A \cap B) \ge c(A)$ となります．&lt;br&gt;
この不等式をカットの劣モジュラ性である $c(A) + c(B) \ge c(A \cap B) + c(A \cup B)$ に代入することで，$c(A \cup B) \le c(B)$ を得ます．&lt;/li&gt;
&lt;li&gt;$c(A \cup B) \ge c(B)$&lt;br&gt;
$B$ は最小 u - v カットで $A \cup B$ も u - v カットであるため，$c(A \cup B) \ge c(B)$ を得ます．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上により，$A \cup B$ は最小 u - v カットといえます．$A \cup B$ を新しく $B$ ととることで，$A \subseteq B$ であるような最小 u - v カット $B$ とすることができます．&lt;/p&gt;
&lt;h3 id="gomory-hu-木の性質"&gt;Gomory-Hu 木の性質
&lt;/h3&gt;&lt;p&gt;Gomory-Hu 木の定義から Gomory-Hu 木の性質が導かれることを示します．&lt;/p&gt;
&lt;p&gt;$T$ の s - t パス上の最小重みの辺を $(a, b) \in F$ とします．このとき，$C_{ab}$ は s - t カットとなり，最小 s - t カットの容量 $\lambda_{s, t}$ が $w(a, b)$ と一致することを示します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\lambda_{s, t} \ge w(a, b)$&lt;br&gt;
s - t パスの頂点列を考えます．&lt;br&gt;
$v_1 = s$，$v_k = t$ とすると，補題 1 より $\lambda_{s, t} \ge \min \limits_{1 \le i \le k - 1} \lambda_{v_i, v_{i + 1}}$ が成り立ちます．&lt;br&gt;
Gomory-Hu 木の定義より $\min \limits_{1 \le i \le k - 1} \lambda_{v_i, v_{i + 1}} = \lambda_{a, b} = w(a, b)$ なので，$\lambda_{s, t} \ge w(a, b)$ が成り立ちます．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\lambda_{s, t} \le w(a, b)$&lt;br&gt;
$\lambda_{s, t}$ は定義より最小 s - t カットの値です．&lt;br&gt;
辺 $(a, b) \in F$ は $s$ から $t$ への唯一のパス上に存在するため，$C_{ab}$ は s - t カットでもあります．このカットの容量は Gomory-Hu 木の定義から $w(a, b)$ です．よって，$\lambda_{s, t} \le c(C_{ab}) = w(a, b)$ が成り立ちます．&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上により，$C_{ab}$ が s - t カットであり，$\lambda_{s, t} = w(a, b)$ となることが示せました．&lt;/p&gt;
&lt;h2 id="gomory-hu-のアルゴリズム"&gt;Gomory-Hu のアルゴリズム
&lt;/h2&gt;&lt;p&gt;Gomory-Hu 木 $T$ を構築するアルゴリズムを説明します．&lt;br&gt;
Gomory-Hu 木は，木の各辺がある頂点対の最小カットを表し，その結果として任意の $2$ 頂点間の最小カットが木上で読み取れるという形になっていました．&lt;br&gt;
そこで直感的には，最初に $G$ のすべての頂点を $1$ つの縮約頂点として持ち，辺がある頂点対の最小カットとなるように縮約頂点を分割していくことで木を構築すればよさそうです．&lt;br&gt;
ただし，適当に分割してしまうと以前の分割と交差してしまいすでに作った構造を壊してしまうことがあります．&lt;br&gt;
Gomory-Hu のアルゴリズムはこの問題に対処するために，すでにできている縮約頂点をそれぞれ 1 頂点に縮約したグラフの上で最小カットを計算し，その結果を使って縮約頂点を分割します．&lt;br&gt;
こうすると新しい分割は以前の分割を壊さない形で実行することができるため，分割を積み重ねながら木を安全に構築できます．&lt;br&gt;
具体的なアルゴリズムは以下の通りです．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;初期化&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$V(T) = \{V(G)\}$&lt;/li&gt;
&lt;li&gt;$E(T) = \emptyset$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;要素数が $2$ 以上の $X \in V(T)$ がある間以下を行う．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$X$ の中から異なる $2$ 頂点 $s, t \in X$ を選ぶ．&lt;/li&gt;
&lt;li&gt;縮約グラフ $H$ を構築する．
&lt;ul&gt;
&lt;li&gt;$T$ から $X$ を削除したときの連結成分を $C_1, C_2, \cdots, C_k$ とし，$C_i$ のすべての要素の和集合を $S_i$ とする．&lt;/li&gt;
&lt;li&gt;$G$ 上で各 $S_i$ を $1$ つの頂点に縮約したグラフを $H$ とする．縮約で生じる並行辺は維持し，同一成分内の辺を除去する．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$H$ 上で最小 s - t カット $S$ を求め，$A = X \cap S$，$B = X \setminus S$ とする．&lt;/li&gt;
&lt;li&gt;$X$ を $A$ と $B$ に分割する．
&lt;ul&gt;
&lt;li&gt;$V(T) = (V(T) - \{ X\}) \cup \{A, B\}$ と更新する．&lt;/li&gt;
&lt;li&gt;新しい辺 $AB$ を $T$ に追加し，その重みを先程求めた最小 s - t カットの値とする．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;既存の辺を置き換える．
&lt;ul&gt;
&lt;li&gt;$X$ に接続する辺 $XY \in E(T)$について以下を行う．
&lt;ul&gt;
&lt;li&gt;$XY$ を $E(T)$ から削除する．&lt;/li&gt;
&lt;li&gt;$Y$ が属する側の縮約頂点 $v_{S_i}$ について，$v_{S_i} \in S$ なら $AY$ を，そうでないなら $BY$ を追加する．追加する辺の重みは $XY$ と同じとする．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;単一集合となったすべての頂点 $\{v\}$ について以下を行う．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;頂点 $\{v\}$ を $v$ に，辺 $(\{u\}, \{v\})$ を $(u, v)$ に置き換える．&lt;/li&gt;
&lt;li&gt;Gomory-Hu 木 $(V(T), E(T))$ を返す．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="アルゴリズムの実行例"&gt;アルゴリズムの実行例
&lt;/h2&gt;&lt;p&gt;下のグラフの Gomory-Hu 木を求めます．&lt;br&gt;
&lt;img src="images/s-t-cut_sample1.png" width="50%"&gt;&lt;/p&gt;
&lt;h3 id="phase-1"&gt;Phase 1
&lt;/h3&gt;&lt;p&gt;はじめ，$V(T) = \{ \{1, 2, 3, 4, 5, 6\} \}$ です．&lt;br&gt;
$X$ として $\{1, 2, 3, 4, 5, 6\}$ を選び，縮約グラフ $H$ を構築します．&lt;br&gt;
今回は $X$ に接続する辺はないので，$H = G$ となります．&lt;br&gt;
下の左の図が $T$ で，右の図が $H$ です．&lt;/p&gt;
&lt;img src="images/t1.png" width="30%"&gt;
&lt;img src="images/h1.png" width="30%"&gt;
&lt;ul&gt;
&lt;li&gt;最小 s - t カットの計算&lt;br&gt;
$s$ と $t$ は任意に選べます．今回は $s = 3$，$t = 5$ として，$H$ での最小 s - t カットを求めると，$S = \{1, 3\}$ となり，その容量は $10$ です．&lt;/li&gt;
&lt;li&gt;$X$ の分割&lt;br&gt;
$X$ を $A = X \cap S = \{1, 3\}$ と $B = X \setminus S = \{2, 4, 5, 6\}$ に分割し，重み $10$ の辺を張ります．&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらの操作により，$T$ は以下のようになります．&lt;/p&gt;
&lt;img src="images/t2-1.png" width="30%"&gt;
&lt;hr&gt;
&lt;h3 id="phase-2"&gt;Phase 2
&lt;/h3&gt;&lt;p&gt;$X$ として $\{2, 4, 5, 6\}$ を選び，縮約グラフ $H$ を構築します．&lt;br&gt;
$G$ について，$T$ から $X$ を削除したときの連結成分 $C_1$ の展開 $S_1$ を $1$ つの頂点 $v_{S_1}$ として縮約します．&lt;/p&gt;
&lt;img src="images/t2.png" width="30%"&gt;
&lt;img src="images/h2.png" width="30%"&gt;
&lt;ul&gt;
&lt;li&gt;最小 s - t カットの計算&lt;br&gt;
$s = 5, t = 4$ とすると，$H$ での最小 s - t カットは $S = \{\{1, 3\}, 2, 5\}$ となり，その容量は $14$ です．&lt;/li&gt;
&lt;li&gt;$X$ の分割&lt;br&gt;
$X$ を $A = \{2, 5\}$ と $B = \{4, 6\}$ に分割し，重み $14$ の辺を張ります．&lt;/li&gt;
&lt;li&gt;既存の辺の付け替え&lt;br&gt;
$X$ の分割後，更新前の $T$ の辺 $(\{1, 3\}, X)$ がどうなるか考えます．$v_{S_1} \in S$ であるため，この辺は $A$ と接続します．&lt;br&gt;
よって辺 $(\{1, 3\}, X)$ は辺 $(\{1, 3\}, A)$ に付け替えられます．&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/t3-1.png" width="30%"&gt;
&lt;hr&gt;
&lt;h3 id="phase-3"&gt;Phase 3
&lt;/h3&gt;&lt;p&gt;$X$ として $\{1, 3\}$ を選び，縮約グラフ $H$ を構築します．&lt;br&gt;
$S_1$ を $1$ つの頂点 $v_{S_1}$ として縮約します．&lt;/p&gt;
&lt;img src="images/t3.png" width="30%"&gt;
&lt;img src="images/h3.png" width="30%"&gt;
&lt;ul&gt;
&lt;li&gt;最小 s - t カットの計算&lt;br&gt;
$s = 1, t = 3$ とすると，グラフ $H$ での最小 s - t カットは $S = \{1\}$ となり，その容量は $7$ です．&lt;/li&gt;
&lt;li&gt;$X$ の分割&lt;br&gt;
$X$ を $A = \{1\}$ と $B = \{3\}$ に分割し，重み $7$ の辺を張ります．&lt;/li&gt;
&lt;li&gt;既存の辺の付け替え&lt;br&gt;
$X$ の分割後，更新前の $T$ の辺 $(X, \{2, 5\})$ がどうなるか考えます．$v_{S_1} \notin S$ であるため，この辺は $B$ と接続します．&lt;br&gt;
よって辺 $(X, \{2, 5\})$ は辺 $(B, \{2, 5\})$ に付け替えられます．&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/t4-1.png" width="30%"&gt;
&lt;hr&gt;
&lt;h3 id="phase-4"&gt;Phase 4
&lt;/h3&gt;&lt;p&gt;$X$ として $\{2, 5\}$ を選び，縮約グラフ $H$ を構築します．&lt;br&gt;
$S_1$ と $S_2$ をそれぞれ $1$ つの頂点 $v_{S_1}, v_{S_2}$ として縮約します．&lt;/p&gt;
&lt;img src="images/t4.png" width="30%"&gt;
&lt;img src="images/h4.png" width="30%"&gt;
&lt;ul&gt;
&lt;li&gt;最小 s - t カットの計算&lt;br&gt;
$s = 2, t = 5$ とすると，グラフ $H$ での最小 s - t カット $S$ は $\{2\}$ となり，その容量は $8$ です．&lt;/li&gt;
&lt;li&gt;$X$ の分割&lt;br&gt;
$X$ を $A = \{2\}$ と $B = \{5\}$ に分割し，重み $8$ の辺を張ります．&lt;/li&gt;
&lt;li&gt;既存の辺の付け替え&lt;br&gt;
$X$ の分割後，更新前の $T$ の辺 $(\{3\}, X)$ がどうなるか考えます．&lt;br&gt;
$v_{S_1} \notin S$ であるため，この辺は $B$ と接続します．
また，更新前の $T$ の辺 $(X, \{4, 6\})$ は $v_{S_2} \notin S$ であるため，この辺も $B$ と接続します．&lt;br&gt;
よって辺 $(\{3\}, X)$ は辺 $(\{3\}, B)$ に，辺 $(X, \{4, 6\})$ は $(B, \{4, 6\})$ に付け替えられます．&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/t5-1.png" width="30%"&gt;
&lt;hr&gt;
&lt;h3 id="phase-5"&gt;Phase 5
&lt;/h3&gt;&lt;p&gt;$X$ として $\{4, 6\}$ を選び，縮約グラフ $H$ を構築します．&lt;br&gt;
$S_1$ を $1$ つの頂点 $v_{S_1}$ として縮約します．&lt;/p&gt;
&lt;img src="images/t5.png" width="30%"&gt;
&lt;img src="images/h5.png" width="30%"&gt;
&lt;ul&gt;
&lt;li&gt;最小 s - t カットの計算&lt;br&gt;
$s = 4, t = 6$ とすると，グラフ $H$ での最小 s - t カット $S$ は $\{4, \{1, 2, 3, 5\}\}$ となり，その容量は $12$ です．&lt;/li&gt;
&lt;li&gt;$X$ の分割&lt;br&gt;
$X$ を $A = \{4\}$ と $B = \{6\}$ に分割し，重み $12$ の辺を張ります．&lt;/li&gt;
&lt;li&gt;既存の辺の付け替え&lt;br&gt;
$X$ の分割後，更新前の $T$ の辺 $(5, X)$ がどうなるか考えます．$v_{S_1} \in S$ であるため，この辺は $A$ と接続します．&lt;br&gt;
よって辺 $(5, X)$ は辺 $(5, A)$ に付け替えられます．&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/t6-1.png" width="30%"&gt;
&lt;hr&gt;
&lt;h3 id="phase-6"&gt;Phase 6
&lt;/h3&gt;&lt;p&gt;$T$ のすべての頂点の要素数が $1$ なので Step 2 を終了します．&lt;br&gt;
Step 3 は省略します．&lt;/p&gt;
&lt;img src="images/t6.png" width="30%"&gt;
&lt;h2 id="証明"&gt;証明
&lt;/h2&gt;&lt;p&gt;アルゴリズムが Gomory-Hu 木を構築する証明をします．&lt;br&gt;
表記を整理しておきます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\lambda_{s,t;G}$：グラフ $G$ の最小 s - t カットの容量&lt;/li&gt;
&lt;li&gt;$\lambda_{s,t;H}$：縮約グラフ $H$ の最小 s - t カットの容量&lt;/li&gt;
&lt;li&gt;$w(YZ)$：木 $T$ の辺 $YZ$ の重み&lt;/li&gt;
&lt;li&gt;$C^{\prime}_{YZ}$：木 $T$ から辺 $YZ$ を削除したときにできる 2 つの連結成分のうち，$Y$ に属する連結成分をすべて展開したもの&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;アルゴリズムの開始時と各イテレーション終了時に，次の不変条件が成り立つことを示します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;木 $T$ の任意の辺 $YZ$ に対してある頂点 $s \in Y, t \in Z$ が存在し，$C^{\prime}_{YZ}$ は元のグラフ $G$ における最小 s - t カットであり，$\lambda_{s, t;G} = w(YZ)$ となる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まず，アルゴリズムの開始時には辺がないので不変条件は成り立ちます．&lt;br&gt;
このあとで，各イテレーション時に以下の $3$ つの辺について不変条件が成り立つことを示します．&lt;/p&gt;
&lt;ol type="a"&gt;
&lt;li&gt;新しく追加される辺 $AB$&lt;/li&gt;
&lt;li&gt;既存の辺 $XY$ から付け替えられた辺&lt;/li&gt;
&lt;li&gt;その他の辺&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;アルゴリズムの終了時には縮約頂点はすべて展開され，木 $T$ は Gomory-Hu 木の定義を満たしているため，アルゴリズムは Gomory-Hu 木を構築するといえます．&lt;/p&gt;
&lt;h3 id="a-新しく追加される辺"&gt;a. 新しく追加される辺 $AB$
&lt;/h3&gt;&lt;p&gt;アルゴリズムは縮約グラフ $H$ 上で $s, t \in X$ について最小 s - t カット $S$ を求め，$A = X \cap S$，$B = X \setminus S$ と分割します．その上で，辺 $AB$ の重み $w(AB)$ を $\lambda_{s,t;H}$ とします．&lt;/p&gt;
&lt;p&gt;辺 $AB$ が不変条件を満たすことを示すため，以下を確認します．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;$H$ 上の最小 s - t カットを展開した頂点集合は $G$ 上の最小 s - t カットとなりその容量は一致する．つまり，$\lambda_{s, t;G} = w(AB) = \lambda_{s,t;H}$ となる&lt;/li&gt;
&lt;li&gt;$H$ 上の最小 s - t カットを展開した頂点集合は $C^{\prime}_{AB}$ となる&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="1--上の最小-s---t-カットを展開した頂点集合は--上の最小-s---t-カットとなりその容量は一致する"&gt;1. $H$ 上の最小 s - t カットを展開した頂点集合は $G$ 上の最小 s - t カットとなりその容量は一致する
&lt;/h4&gt;&lt;p&gt;アルゴリズムのあるイテレーションで，$S_1, \cdots, S_k$ を順番に縮約していくことを考えます．$S_i$ までを縮約したグラフを $H_i$ とします．$H_0$ はグラフ $G$ に，$H_k$ はアルゴリズムで述べられている縮約グラフ $H$ に一致します．&lt;/p&gt;
&lt;p&gt;不変条件より，木の各辺 $YZ$ に対してある頂点対 $(s_{YZ}, t_{YZ})$ が存在し，$C^{\prime}_{YZ}$ は $G$ 上の最小 $s_{YZ}$ - $t_{YZ}$ カットになっています．頂点 $X \in T$ を削除したときの連結成分 $C_i$ と $X$ を結ぶ辺を $Y_i X$ とおくと，$S_i = C^{\prime}_{Y_i X}$ が成り立ちます．&lt;br&gt;
よって，各 $S_i$ はある頂点対 $(s_i, t_i)$ に対する最小 $s_i$ - $t_i$ カットです．&lt;br&gt;
また，$S_i$ は $T \setminus X$ の連結成分から構成されているので，$s, t \notin S_i$ です．&lt;/p&gt;
&lt;p&gt;各ステップ $i$ について，$H_i$ には $G$ における最小 s - t カットの容量である $\lambda_{s, t;G}$ と同じ容量の s - t カットが存在することを帰納法で示します．&lt;br&gt;
$i = 0$ のとき，$H_0 = G$ なので自明です．&lt;br&gt;
帰納法の仮定より，$H_i$ には容量 $\lambda_{s, t;G}$ の s - t カット $C$ があります．このとき，$S_{i + 1}$ を縮約して得られる $H_{i + 1}$ にも容量 $\lambda_{s, t;G}$ の s - t カットが存在することを示します．&lt;br&gt;
補題 2 により $H_i$ の s - t カット $C$ は $S_{i + 1}$ を交差しないようにとりなおすことができます．よって，$S_{i + 1}$ を縮約して $H_{i + 1}$ を構築しても，容量 $\lambda_{s, t;G}$ の s - t カットが存在するといえます．&lt;br&gt;
よって，$H$ には容量 $\lambda_{s, t;G}$ の s - t カットが存在することが示せました．&lt;/p&gt;
&lt;p&gt;任意の $H$ 上の s - t カットは，縮約を展開すれば $G$ 上の s - t カットになります．縮約は辺の容量を変えないので，カットの容量も維持されます．&lt;br&gt;
したがって，任意の $H$ 上の s - t カットの容量 = 対応する $G$ 上の s - t カットの容量 $\ge \lambda_{s, t;G}$ となり，$H$ の最小 s - t カットの容量は $\lambda_{s, t;G}$ となります．&lt;/p&gt;
&lt;h4 id="2--上の最小-s---t-カットを展開した頂点集合は--となる"&gt;2. $H$ 上の最小 s - t カットを展開した頂点集合は $C^{\prime}_{AB}$ となる
&lt;/h4&gt;&lt;p&gt;$H$ の最小 s - t カット $S$ を展開して得られる頂点集合は，アルゴリズムにおける辺の付け替え規則から，更新後の木 $T^{\prime}$ で辺 $AB$ を削除したときの $A$ 側成分 $C^{\prime}_{AB}$ と一致します．&lt;br&gt;
これは，$X$ 内の頂点のうち $S$ に属するものは $A$ に，また各連結成分 $C_i$ に対応する縮約頂点 $v_{S_i}$ が $S$ に属する場合に限り，その成分は $A$ 側に接続されるように付け替えられているためです．&lt;/p&gt;
&lt;p&gt;以上のことから辺 $AB$ が不変条件を満たすことがわかりました．&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="b-既存の辺--から付け替えられた辺"&gt;b. 既存の辺 $XY$ から付け替えられた辺
&lt;/h3&gt;&lt;p&gt;アルゴリズムは，縮約グラフ $H$ 上で $s, t \in X$ について最小 s - t カット $S$ を見つけ，$X$ を $A = X \cap S$ と $B = X \setminus S$ に分割します．もともと $X$ と $Y$ の間に張られていた辺 $XY$ は $A$ に付け替えられて $AY$ になるか，$B$ に付け替えられて $BY$ になります．&lt;br&gt;
以降は $A$ に付け替えられた場合を考えますが $B$ でも同じことがいえます．&lt;/p&gt;
&lt;p&gt;$p \in X$，$q \in Y$ であり，XY の重みは $\lambda_{p, q}$ であったとします．&lt;br&gt;
&lt;img src="images/replace0.png" width="30%"&gt;&lt;/p&gt;
&lt;p&gt;$X$ の最小 s - t カットを求め，$A$ と $B$ に分割したとき，$s \in A$，$t \in B$ であるとします．&lt;br&gt;
$A$ と $B$ は $X$ を分割したものであるため，$C^{\prime}_{AY} = C^{\prime}_{XY}$ とみなすことができます．&lt;br&gt;
辺 $AY$ の重みが $\lambda_{p, q}$ であることを $p \in A$ の場合と $p \notin A$ の場合について示します．&lt;/p&gt;
&lt;p&gt;$p \in A$ の場合&lt;br&gt;
&lt;img src="images/replace1.png" width="30%"&gt;&lt;/p&gt;
&lt;p&gt;辺 $AY$ の重みは $\lambda_{p, q}$ なので，不変条件を満たします．&lt;/p&gt;
&lt;p&gt;$p \notin A$ の場合&lt;br&gt;
&lt;img src="images/replace2.png" width="30%"&gt;&lt;/p&gt;
&lt;p&gt;$\lambda_{s, q} = \lambda_{p, q}$ であることを示します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\lambda_{s, q} \ge \lambda_{p, q}$&lt;br&gt;
頂点列 $s, t, p, q$ を考えると補題 1 より $\lambda_{s, q} \ge \min \{\lambda_{s, t}, \lambda_{t, p}, \lambda_{p, q} \}$ が言えます．&lt;br&gt;
$H$ 上の最小 s - t カットを展開したものを $\bar S$ とします．&lt;br&gt;
このとき，$s, q \in \bar S$，$t, p \in B \subseteq V \setminus \bar S$ です．&lt;/p&gt;
&lt;p&gt;カット関数は対称なので $V \setminus \bar S$ も最小 s - t カットです．&lt;br&gt;
そこで，補題 2 を $A = V \setminus \bar S$，$(u, v) = (s, q)$ に適用します（このとき $s, q \notin A$ が成り立ちます）．&lt;br&gt;
すると，ある最小 s - q カット $C^{\prime}$ が存在して&lt;/p&gt;
$$(V \setminus \bar S) \subseteq C^{\prime} \text{または} (V \setminus \bar S) \cap C^{\prime} = \emptyset$$&lt;p&gt;が成り立ちます．&lt;br&gt;
前者なら無向グラフなので $V \setminus C^{\prime}$ も最小 s - q カットであり，こちらは $(V \setminus \bar S) \cap (V \setminus C^{\prime}) = \emptyset$ となるので，$C = V \setminus C^{\prime} \subseteq \bar S$ とできます．&lt;br&gt;
後者ならそのまま $C = C^{\prime}$ とおけば $C \subseteq \bar S$ です．&lt;br&gt;
よって，ある最小 s - q カット $C$ は，$C \subseteq \bar S$ であるようにとることができます．&lt;br&gt;
つまり，最小 s - q カットは $t, p \in B$ となるようにとれるので，$\lambda_{s, q}$ は 辺 $(t, p)$ の容量に依存しないことがわかります．&lt;br&gt;
よって，大きな容量をもつ辺 $(t, p)$ を追加したとしても不等式が成り立ち，$\lambda_{s, q} \ge \min \{\lambda_{s, t}, \lambda_{p, q} \}$ が成立します．&lt;br&gt;
また，最小 s - t カットは p-q カットでもあるため，$\lambda_{s, t} \ge \lambda_{p, q}$ が成り立ちます．&lt;br&gt;
よって，$\lambda_{s, q} \ge \lambda_{p, q}$ が示せました．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\lambda_{s, q} \le \lambda_{p, q}$&lt;br&gt;
$C^{\prime}_{XY}$ は $X$ と $Y$ を分けるカットであり，$p \in X$ と $q \in Y$ を分離していて，重みは $\lambda_{p, q}$ でした．&lt;br&gt;
$s \in A \subset X$ なので，$C^{\prime}_{XY}$ は s - q カットでもあります．&lt;br&gt;
よって，$\lambda_{s, q} \le \lambda_{p, q}$ が示せました．&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上より，$\lambda_{s, q} \ge \lambda_{p, q}$ と $\lambda_{s, q} \le \lambda_{p, q}$ の両方が示せたので，$\lambda_{s, q} = \lambda_{p, q}$ が成り立ちます．したがって $w(AY)=w(XY)=\lambda_{p,q}=\lambda_{s,q}$ であり，$s \in A,\, q \in Y$ をとれば辺 $AY$ も不変条件を満たします．&lt;/p&gt;
&lt;h3 id="c-その他の辺"&gt;c. その他の辺
&lt;/h3&gt;&lt;p&gt;アルゴリズムで選んだ $X$ に接続していない辺 $YZ$ は，木 $T$ 上での位置も対応するカット $C^{\prime}_{YZ}$ も変化しないため，不変条件を満たします．&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doi.org/10.1137%2F0109047" target="_blank" rel="noopener"
&gt;Multi-Terminal Network Flows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://webdocs.cs.ualberta.ca/~zacharyf/courses/combopt_2016/notes/lec5.pdf" target="_blank" rel="noopener"
&gt;Lecture 5 (Sept. 16): Undirected Cuts and Gomory-Hu Trees&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://webdocs.cs.ualberta.ca/~zacharyf/courses/combopt_2016/notes/lec6.pdf" target="_blank" rel="noopener"
&gt;Lecture 6 (Sept. 19): Gomory-Hu Trees&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.contrib.andrew.cmu.edu/~ravi/book.pdf" target="_blank" rel="noopener"
&gt;Iterative Methods in Combinatorial Optimization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;カット関数は $G$ に対して定義されています&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;必要に応じて，$B$ を $V \setminus B$ に置き換える操作と名前の付け替えを行います&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Adwords に対する Primal-Dual の競合比解析</title><link>https://miti-7.github.io/post/adwords-primal-dual/</link><pubDate>Fri, 12 Sep 2025 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/adwords-primal-dual/</guid><description>&lt;h2 id="adwords"&gt;Adwords
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://miti-7.github.io/post/adwords-greedy-primal-dual/" target="_blank" rel="noopener"
&gt;Adwords に対する Primal-Dual を使った貪欲法の競合比解析&lt;/a&gt; の続きです．&lt;br&gt;
以下では，adwords に対する primal dual algorithm が $1 - \frac{1}{e}$-competitive となることを示します．&lt;/p&gt;
&lt;h2 id="small-bids-assumption"&gt;Small Bids Assumption
&lt;/h2&gt;&lt;p&gt;予算に対する入札額の比率のうち最大を $R_{\mathrm{max}}$ とし，$R_{\mathrm{max}}$ は十分小さいと仮定します．&lt;br&gt;
$R_{\mathrm{max}} \coloneqq \max_{u, v} \frac{\mathrm{bid}_{uv}}{B_u}$&lt;/p&gt;
&lt;h2 id="adwords-の定式化"&gt;Adwords の定式化
&lt;/h2&gt;&lt;p&gt;Adwords の主問題と双対問題は以下のようになります．ここでは adwords を双対問題とします．&lt;br&gt;
$x_{uv}$ は $v$ が $u$ に割り当てられたときに $1$ になる決定変数です．実際には広告リクエストは分割できないので $x_{uv} \in \lbrace 0, 1 \rbrace$ ですが線形緩和しています．&lt;/p&gt;
&lt;p&gt;主問題(Primal Problem)&lt;/p&gt;
$$
\begin{aligned}
&amp;\text{minimize} &amp;&amp; \sum_{u} B_u \alpha_{u} + \sum_{v} \beta_v \\
&amp;\text{subject to}
&amp;&amp; \mathrm{bid}_{uv}(1 - \alpha_u) \leq \beta_v &amp;&amp; \forall u, v \\
&amp; &amp;&amp; \alpha_u \geq 0 \\
&amp; &amp;&amp; \beta_{v} \geq 0
\end{aligned}
$$&lt;p&gt;双対問題(Dual Problem)&lt;/p&gt;
$$
\begin{aligned}
&amp;\text{maximize} &amp;&amp; \sum_{u, v} \mathrm{bid}_{uv} x_{uv} \\
&amp;\text{subject to}
&amp;&amp; \sum_{v} \mathrm{bid}_{uv} x_{uv} \le B_u &amp;&amp; \forall u \\
&amp; &amp;&amp; \sum_u x_{uv} \leq 1 &amp;&amp; \forall v \\
&amp; &amp;&amp; x_{uv} \geq 0
\end{aligned}
$$&lt;h2 id="アルゴリズム"&gt;アルゴリズム
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;初期化
&lt;ul&gt;
&lt;li&gt;各 $u$ について，$\alpha_u \leftarrow 0$ とする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$v$ が到着したとき，$\alpha_u \lt 1$ の中で $\mathrm{bid}_{uv}(1 - \alpha_u)$ を最大化する $u$ に $v$ を割り当てる&lt;/li&gt;
&lt;li&gt;$\alpha_u \ge 1$ ならなにもしない．そうでなければ
&lt;ul&gt;
&lt;li&gt;$u$ の残り予算から $\min(\mathrm{bid}_{uv}, 残り予算)$ 減算し，$x_{uv} \leftarrow 1$ とする&lt;/li&gt;
&lt;li&gt;$\beta_v \leftarrow \mathrm{bid}_{uv}(1 - \alpha_u)$&lt;/li&gt;
&lt;li&gt;$\alpha_u \leftarrow \alpha_u (1 + \frac{\mathrm{bid}_{uv}}{B_u}) + \frac{\mathrm{bid}_{uv}}{(c - 1) \cdot B_u}$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="競合比解析"&gt;競合比解析
&lt;/h2&gt;&lt;p&gt;以下の 3 つを示します．
主問題の目的関数値と双対問題の目的関数値を $P$ と $D$ とし，$1$ イテレーションでの変化量をそれぞれ $\Delta P$ と $\Delta D$ で表します．&lt;br&gt;
また，$R_{\mathrm{max}} = \max_{u, v}{\frac{\mathrm{bid}_{uv}}{B_u}}$，$c = (1 + R_{\mathrm{max}})^{\frac{1}{R_{\mathrm{max}}}}$ とします．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;主問題の実行可能解を生成する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;双対問題の（ほぼ）実行可能解を生成する&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;双対問題の予算制約を破ることがあるが，各 $u$ の超過は高々 $\max_{v} \mathrm{bid}_{uv}$&lt;/li&gt;
&lt;li&gt;得られる利益は $(1 - R_{\mathrm{max}})\sum_{uv} \mathrm{bid}_{uv} x_{uv}$ 以上となる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;各イテレーションで $\Delta P \le (1 + \frac{1}{c - 1}) \Delta D$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\frac{\Delta D}{\Delta P} \ge 1 - \frac{1}{c}$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1.，2.，3.と弱双対性により上記のアルゴリズムの競合比は以下のようになります．
&lt;/p&gt;
$$(1 - \frac{1}{c})(1 - R_{\mathrm{max}}) = (1 - \frac{1}{(1 + R_{\mathrm{max}})^{\frac{1}{R_{\mathrm{max}}}}})(1 - R_{\mathrm{max}})$$&lt;p&gt;これは，$R_{\mathrm{max}} \rightarrow 0^+$ のとき $1 - \frac{1}{e}$ に近づきます．&lt;/p&gt;
&lt;h3 id="1-主問題の実行可能解を生成する"&gt;1. 主問題の実行可能解を生成する
&lt;/h3&gt;&lt;p&gt;主問題の制約条件は $(1)$ $\mathrm{bid}_{uv}(1 - \alpha_u) \leq \beta_v$，$(2)$ $\alpha_u \geq 0$，$(3)$ $\beta_{v} \geq 0$ の 3 つです．&lt;br&gt;
$(2)$ と $(3)$ は明らかに満たしているので，$(1)$ を満たすことを確認します．&lt;/p&gt;
&lt;p&gt;$v$ が $u$ に割り当てられたときを考えます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\alpha_u \ge 1$ の場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\mathrm{bid}_{uv} \ge 0$ かつ $\beta_v \ge 0$のため制約 $(1)$ を満たします．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\alpha_u \lt 1$ の場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アルゴリズムで $\beta_v = \mathrm{bid}_{uv}(1 - \alpha_u)$となります．&lt;br&gt;
このとき $u$ として $\mathrm{bid}_{u^{\prime} v}(1 - \alpha_{u^{\prime}})$ を最大化する $u^{\prime}$ を選んでいるため，任意の $u$, $v$ について制約 $(1)$ を満たします．&lt;br&gt;
また，アルゴリズムでは $\alpha_i$ を単調増加させるため，この操作によって制約が満たされなくなることはありません．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-双対問題のほぼ実行可能解を生成する"&gt;2. 双対問題の(ほぼ)実行可能解を生成する
&lt;/h3&gt;&lt;p&gt;双対問題の制約条件は，$(1)$ $\sum_{v} \mathrm{bid}_{uv} x_{uv} \le B_u$，$(2)$ $\sum_u x_{uv} \leq 1$，$(3)$ $x_{uv} \geq 0$ の 3 つです．&lt;br&gt;
$(2)$ と $(3)$ は明らかに満たしているので，$(1)$ を満たしていることを確認します．&lt;/p&gt;
&lt;p&gt;まず，アルゴリズムは $\alpha \ge 1$ のとき双対変数を更新しないので，$u$ に対する課金額 $\sum_{v} \mathrm{bid}_{uv} x_{uv}$ が予算を超えたら場合 $\alpha_u \ge 1$ となることを示します．&lt;br&gt;
これは $\alpha_u \ge \frac{1}{c - 1}(c^{\frac{\sum \mathrm{bid}_{uv} x_{uv}}{B_u}} - 1)$ によって示されます．&lt;/p&gt;
&lt;p&gt;$\alpha_u \ge \frac{1}{c - 1}(c^{\frac{\sum_{v} \mathrm{bid}_{uv} x_{uv}}{B_u}} - 1)$ を帰納法を使って証明します．&lt;br&gt;
$\alpha_u \ge \frac{1}{c - 1}(c^{\frac{\sum_{v} \mathrm{bid}_{uv} x_{uv}}{B_u}} - 1)$ を仮定します．はじめこの条件は明らかに満たされています．&lt;br&gt;
$k$ が $u$ に割り当てられたときの $\alpha_{u}$ の変化量を考えます．&lt;/p&gt;
$$
\begin{aligned}
\alpha_{u_{end}} &amp;= \alpha_{u_{start}}(1 + \frac{\mathrm{bid}_{uk}}{B_u}) + \frac{\mathrm{bid}_{uk}}{(c - 1)B_u} \\
&amp;\ge \frac{1}{c - 1} [c^{\frac{\sum_{v \in V \backslash \{k\}} \mathrm{bid}_{uv} x_{uv}}{B_u}} - 1](1 + \frac{\mathrm{bid}_{uk}}{B_u}) + \frac{\mathrm{bid}_{uk}}{(c - 1)B_u} \\
&amp;= \frac{1}{c - 1}[c^{\frac{\sum_{v \in V \backslash \{k\}} \mathrm{bid}_{uv} x_{uv}}{B_u}}(1 + \frac{\mathrm{bid}_{uk}}{B_u}) - 1] \\
&amp;\ge \frac{1}{c - 1}[c^{\frac{\sum_{v \in V \backslash \{k\}} \mathrm{bid}_{uv} x_{uv}}{B_u}} c^{\frac{\mathrm{bid}_{uk}}{B_u}} - 1] \\
&amp;= \frac{1}{c - 1}[c^{\frac{\sum_{v} \mathrm{bid}_{uv} x_{uv}}{B_u}} - 1]
\end{aligned}
$$&lt;details&gt;&lt;summary&gt;補足&lt;/summary&gt;&lt;div&gt;
&lt;hr&gt;
&lt;p&gt;$2$ つめの不等式は帰納法の仮定から導かれます．&lt;br&gt;
$4$ つめの不等式が成り立つことを示すために，$1 + \frac{\mathrm{bid}_{uk}}{B_u} \ge c^{\frac{\mathrm{bid}_{uk}}{B_u}}$ を示します．&lt;br&gt;
$0 \le x \le y \le 1$ のとき，$\frac{\ln(1 + x)}{x} \ge \frac{\ln(1 + y)}{y}$ となることを利用します．&lt;br&gt;
ここで，$x = \frac{\mathrm{bid}(uk)}{B_u} \le R_{\mathrm{max}} = y$ とおくと，
&lt;/p&gt;
$$\frac{\ln(1 + x)}{x} \ge \frac{\ln(1 + R_{\mathrm{max}})}{R_{\mathrm{max}}} = \ln((1 + R_{\mathrm{max}})^{\frac{1}{R_{\mathrm{max}}}}) = \ln c$$&lt;p&gt;
両辺を $x$ 倍して指数をとると $1 + x \ge c^{x}$ となることから $1 + \frac{\mathrm{bid}_{uk}}{B_u} \ge c^{\frac{\mathrm{bid}_{uk}}{B_u}}$ が示せました．&lt;br&gt;
また，$\frac{\mathrm{bid}_{uk}}{B_u} = R_{\mathrm{max}}$ のとき，この不等式は等式で成り立ちます．そのため，$c = (1 + R_{\mathrm{max}})^{\frac{1}{R_{\mathrm{max}}}}$ としているのでした．&lt;/p&gt;
&lt;hr&gt;
&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;次に，予算をどれくらい超えるかを考えます．&lt;br&gt;
アルゴリズムでは各 $u$ について予算制約を破る回数は高々 $1$ 回です．&lt;br&gt;
よって $\sum_{v} \mathrm{bid}_{uv} x_{uv} \leq B_{u} + \max_{v} \mathrm{bid}_{uv}$ を満たします．&lt;/p&gt;
&lt;p&gt;$[\sum \mathrm{bid}_{uv} x_{uv}] \frac{B_u}{B_u + \max \mathrm{bid}_{uv}} \ge [\sum \mathrm{bid}_{uv} x_{uv}] (1 - R_{\mathrm{max}})$&lt;br&gt;
よって $(1 - R_{\mathrm{max}})$ をかけることにより確保できる利益の下界がわかります．&lt;/p&gt;
&lt;h3 id="3-各イテレーションで"&gt;3. 各イテレーションで $\Delta P \le (1 + \frac{1}{c - 1}) \Delta D$
&lt;/h3&gt;&lt;p&gt;$\alpha_u \ge 1$ のときはどちらの目的関数値も変化しないので，$\alpha_u \lt 1$ のときを考えます&lt;/p&gt;
&lt;p&gt;$\Delta P$&lt;br&gt;
$\alpha_u \leftarrow \alpha_u (1 + \frac{\mathrm{bid}_{uv}}{B_u}) + \frac{\mathrm{bid}_{uv}}{(c - 1) \cdot B_u}$，$\beta_v \leftarrow \mathrm{bid}_{uv}(1 - \alpha_u)$ とするので&lt;/p&gt;
$$
\begin{aligned}
\Delta P &amp;= B_{u} \Delta \alpha_u + \Delta \beta_v \\
&amp;= B_u(\frac{\mathrm{bid}_{uv} \alpha_u} {B_u} + \frac{\mathrm{bid}_{uv}}{(c - 1)B_{u}}) + \beta_v \\
&amp;= \mathrm{bid}_{uv} \alpha_u + \frac{\mathrm{bid}_{uv}}{c - 1} + \mathrm{bid}_{uv}(1 - \alpha_u) \\
&amp;= \mathrm{bid}_{uv} \alpha_u + \frac{\mathrm{bid}_{uv}}{c - 1} + \mathrm{bid}_{uv} - \mathrm{bid}_{uv} \alpha_u \\
&amp;= \mathrm{bid}_{uv}(1 + \frac{1}{c - 1})
\end{aligned}
$$&lt;p&gt;$\Delta D$&lt;br&gt;
$x_{uv} \leftarrow 1$ とするので&lt;/p&gt;
$$
\begin{aligned}
\Delta D &amp;= \mathrm{bid}_{uv} \Delta x_{uv} \\
&amp;= \mathrm{bid}_{uv}
\end{aligned}
$$&lt;p&gt;よって，$\Delta P \le (1 + \frac{1}{c - 1}) \Delta D$ が示せました．&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://link.springer.com/chapter/10.1007/978-3-540-75520-3_24" target="_blank" rel="noopener"
&gt;Online Primal-Dual Algorithms for Maximizing Ad-Auctions Revenue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ieeexplore.ieee.org/document/8186915" target="_blank" rel="noopener"
&gt;The Design of Competitive Online Algorithms via a Primal-Dual Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://research.google/pubs/online-matching-and-ad-allocation/" target="_blank" rel="noopener"
&gt;Online Matching and Ad Allocation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Adwords に対する Primal-Dual を使った貪欲法の競合比解析</title><link>https://miti-7.github.io/post/adwords-greedy-primal-dual/</link><pubDate>Fri, 12 Sep 2025 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/adwords-greedy-primal-dual/</guid><description>&lt;h2 id="adwords"&gt;Adwords
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://miti-7.github.io/post/adwords-greedy/" target="_blank" rel="noopener"
&gt;Adwords に対する貪欲法の競合比解析&lt;/a&gt; の続きです．&lt;br&gt;
以下では，adwords に対する貪欲法が $\frac{1}{2}$-competitive となることを primal-dual を使って示します．&lt;/p&gt;
&lt;h2 id="small-bids-assumption"&gt;Small Bids Assumption
&lt;/h2&gt;&lt;p&gt;予算に対する入札額の比率のうち最大を $R_{\mathrm{max}}$ とし，$R_{\mathrm{max}}$ は十分小さいと仮定します．&lt;br&gt;
$R_{\mathrm{max}} \coloneqq \max_{u, v} \frac{\mathrm{bid}_{uv}}{B_u}$&lt;/p&gt;
&lt;h2 id="adwords-の定式化"&gt;Adwords の定式化
&lt;/h2&gt;&lt;p&gt;Adwords の主問題と双対問題は以下のようになります．ここでは adwords を双対問題とします．&lt;br&gt;
$x_{uv}$ は $v$ が $u$ に割り当てられたときに $1$ になる決定変数です．実際には広告リクエストは分割できないので $x_{uv} \in \lbrace 0, 1 \rbrace$ ですが線形緩和しています．&lt;/p&gt;
&lt;p&gt;主問題(Primal Problem)&lt;/p&gt;
$$
\begin{aligned}
&amp;\text{minimize} &amp;&amp; \sum_{u} B_u \alpha_{u} + \sum_{v} \beta_v \\
&amp;\text{subject to}
&amp;&amp; \mathrm{bid}_{uv}(1 - \alpha_u) \leq \beta_v &amp;&amp; \forall u, v \\
&amp; &amp;&amp; \alpha_u \geq 0 \\
&amp; &amp;&amp; \beta_{v} \geq 0
\end{aligned}
$$&lt;p&gt;双対問題(Dual Problem)&lt;/p&gt;
$$
\begin{aligned}
&amp;\text{maximize} &amp;&amp; \sum_{u, v} \mathrm{bid}_{uv} x_{uv} \\
&amp;\text{subject to}
&amp;&amp; \sum_{v} \mathrm{bid}_{uv} x_{uv} \le B_u &amp;&amp; \forall u \\
&amp; &amp;&amp; \sum_u x_{uv} \leq 1 &amp;&amp; \forall v \\
&amp; &amp;&amp; x_{uv} \geq 0
\end{aligned}
$$&lt;h2 id="アルゴリズム"&gt;アルゴリズム
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;初期化
&lt;ul&gt;
&lt;li&gt;$x_{uv} \leftarrow 0$，$\alpha_u \leftarrow 0$，$\beta_v \leftarrow 0$ とする&lt;br&gt;
$\alpha_u$ は $u$ が予算を使い切ったときに $1$ になる変数である．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$v$ が到着したとき
&lt;ul&gt;
&lt;li&gt;$\alpha_u = 0$ であるような $u$ （つまり予算を使い切っていない $u$）のうち，$\mathrm{bid}_{uv}$ が最も高い $u^{\prime}$ に $v$ を割り当て，$\beta_v = \mathrm{bid}_{u^{\prime}v}$，$x_{u^{\prime}v} = 1$ とする&lt;/li&gt;
&lt;li&gt;この割り当てで $u^{\prime}$ の予算が $0$ になった場合は，$\alpha_{u^{\prime}} = 1$ とする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="競合比解析"&gt;競合比解析
&lt;/h2&gt;&lt;p&gt;以下の不等式が成り立つことを示します．&lt;/p&gt;
$$\mathrm{ALG} = \mathrm{Dual} \ge \frac{1}{2} \mathrm{Primal} \ge \frac{1}{2} \mathrm{Primal}^{\star} \ge \frac{1}{2} \mathrm{OPT}$$&lt;p&gt;ここで，$\mathrm{Primal}$ と $\mathrm{Dual}$ はアルゴリズムで構築される主問題と双対問題の目的関数値，$\mathrm{Primal}^{\star}$ は主問題の最適解の目的関数値，$\mathrm{OPT}$ は整数問題の最適解の目的関数値です．&lt;br&gt;
以下の 3 つを示します．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;主問題の実行可能解を生成する&lt;/li&gt;
&lt;li&gt;双対問題の実行可能解を生成する&lt;/li&gt;
&lt;li&gt;$\mathrm{Dual} \ge \frac{1}{2} \mathrm{Primal}$&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="1-主問題の実行可能解を生成する"&gt;1. 主問題の実行可能解を生成する
&lt;/h3&gt;&lt;p&gt;主問題の制約条件は $(1)$ $\mathrm{bid}_{uv}(1 - \alpha_u) \leq \beta_v$，$(2)$ $\alpha_u \geq 0$，$(3)$ $\beta_{v} \geq 0$ の 3 つです．&lt;br&gt;
$(2)$ と $(3)$ は明らかに満たしているので，$(1)$ を満たしていることを確認します．&lt;/p&gt;
&lt;p&gt;$\alpha_u = 1$ のとき，$\mathrm{bid}_{uv} (1 - \alpha_u) \le \beta_v$ を満たします．&lt;br&gt;
$\alpha_u = 0$ のとき，$\beta_{v} \ge \mathrm{bid}_{uv}$ となることを確認します．&lt;br&gt;
アルゴリズムは $v$ を $\mathrm{bid}_{uv}$ が最も高くなるような $u^{\prime}$ に割り当て，$\beta_v = \mathrm{bid}_{u^{\prime}v}$ とするので，$\beta_{v} \ge \mathrm{bid}_{uv}$ を満たします．&lt;/p&gt;
&lt;h3 id="2-双対問題の実行可能解を生成する"&gt;2. 双対問題の実行可能解を生成する
&lt;/h3&gt;&lt;p&gt;双対問題の制約条件は，$(1)$ $\sum_{v} bid_{uv} x_{uv} \le B_u$，$(2)$ $\sum_u x_{uv} \leq 1$，$(3)$ $x_{uv} \geq 0$ の 3 つです．&lt;br&gt;
$(2)$ と $(3)$ は明らかに満たしているので，$(1)$ を満たしていることを確認します．&lt;/p&gt;
&lt;p&gt;アルゴリズムでは，予算の残っている $u$ にのみ $v$ を割り当てているので，基本的には制約条件を満たします．&lt;br&gt;
厳密には，$v$ を $u$ に割り当てるとき，$u$ の残り予算が $\mathrm{bid}_{uv}$ に満たない場合でも割り当てることができ予算制約を破る可能性がありますが，small-bids assumption によって競合比には影響しません．&lt;/p&gt;
&lt;h3 id="3"&gt;3. $\mathrm{Dual} \ge \frac{1}{2} \mathrm{Primal}$
&lt;/h3&gt;&lt;p&gt;$v$ を $u$ に割り当てるたび，$\mathrm{Primal}$ も $\mathrm{Dual}$ も $\mathrm{bid}_{uv}(=\beta_v)$ だけ目的関数値が増加します．&lt;br&gt;
また，$\mathrm{Primal}$ は予算を使い切ったとき $\alpha_u = 1$ となり $B_u$ 増加します．この $B_u$ は $u$ に割り当てられた $bid_{uv}$ の合計なので，$\alpha_u = 1$となるような $B_u$ の合計は高々 $\mathrm{Dual}$ となります．&lt;br&gt;
よって，全体として $\mathrm{Primal} \le \mathrm{Dual} + \mathrm{Dual} = 2 \mathrm{Dual}$ なので，$\mathrm{Dual} \ge \frac{1}{2} \mathrm{Primal}$ となります．&lt;/p&gt;
&lt;p&gt;今回の解析では $v$ を $u$ に割り当てるとき，$u$ の残り予算が $\mathrm{bid}_{uv}$ に満たない場合でも $\mathrm{bid}_{uv}$ を計上しています．&lt;br&gt;
よって厳密には高々 $\sum_{u} \max_{v} \mathrm{bid}_{uv}$ を過大に計上していますが，small bids assumption によって，競合比には影響しません．&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://research.google/pubs/online-matching-and-ad-allocation/" target="_blank" rel="noopener"
&gt;Online Matching and Ad Allocation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Adwords に対する貪欲法の競合比解析</title><link>https://miti-7.github.io/post/adwords-greedy/</link><pubDate>Fri, 12 Sep 2025 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/adwords-greedy/</guid><description>&lt;h2 id="adwords"&gt;Adwords
&lt;/h2&gt;&lt;p&gt;広告主の集合 $U$ と広告リクエストの集合 $V$ があります．
各広告主 $u$ は予算 $B_{u}$ を持ちます．広告リクエストは逐次到着し，各広告主は各広告リクエストに対して入札額 $\mathrm{bid}_{uv}$ を設定します．&lt;br&gt;
各広告リクエストが到着するたびに，そのリクエストを一人の広告主に割り当てるか，誰にも割り当てないかを即時に決定します．&lt;br&gt;
割り当てが行われた場合，その広告主の残り予算は $\min(\mathrm{bid}_{uv}, B_{u} - S_{u})$ 減少します．ここで $S_{u}$ は広告主 $u$ の予算消化額です．&lt;br&gt;
全てのリクエストに対して割り当てを決定し，広告主の予算制約を超えない範囲で割り当てられた広告リクエストの入札額の合計を最大化することが目的です．&lt;/p&gt;
&lt;p&gt;以下では，adwords に対する貪欲法が $\frac{1}{2}$-competitive となることを示します．&lt;/p&gt;
&lt;h2 id="アルゴリズム"&gt;アルゴリズム
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;$v$ が到着したとき
&lt;ul&gt;
&lt;li&gt;予算が残っている $u$ がない場合は，どの $u$ にも割り当てない．&lt;/li&gt;
&lt;li&gt;予算が残っている $u$ について，$\widehat{\mathrm{bid}_{uv}} = \min\{\mathrm{bid}_{uv}, B_u - S_u\}$ とし，もっとも $\widehat{\mathrm{bid}_{uv}}$ が高い $u$ に $v$ を割り当てる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="証明"&gt;証明
&lt;/h2&gt;&lt;p&gt;以下のように定義します.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\mathrm{OPT}$: 最適解の目的関数値&lt;/li&gt;
&lt;li&gt;$\mathrm{ALG}$: Greedy の目的関数値&lt;/li&gt;
&lt;li&gt;$\mathrm{opt}_v$: 最適解において，$v$ によって得られる収益&lt;/li&gt;
&lt;li&gt;$\mathrm{alg}_v$: Greedy において，$v$ によって得られる収益&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$\mathrm{OPT} - \mathrm{ALG} \le \mathrm{ALG}$ を示します．&lt;br&gt;
この式が成り立つと，$\mathrm{OPT} \le 2\mathrm{ALG}$ となり，$\frac{1}{2} \mathrm{OPT} \le \mathrm{ALG}$ を示すことができます．&lt;/p&gt;
&lt;p&gt;まず，$\mathrm{OPT} - \mathrm{ALG}$ の上界を求めます．&lt;br&gt;
Greedy が最適解に比べて低い金額で採用してしまった $v$ の集合を $V^{\prime} = \lbrace v : \mathrm{alg}_v \lt \mathrm{opt}_v \rbrace$ と定義し，
$\mathrm{Loss} = \sum_{v \in V^{\prime}} (\mathrm{opt}_v - \mathrm{alg}_v)$ とします．&lt;br&gt;
$\mathrm{alg}_v \ge \mathrm{opt}_v$ であるような $v$ を無視しているので，$\mathrm{Loss}$ は $\mathrm{OPT} - \mathrm{ALG}$ の上界です．&lt;br&gt;
よって，以下のようになります．&lt;/p&gt;
$$
\begin{equation}
\mathrm{OPT} - \mathrm{ALG} = \sum_{v \in V} (\mathrm{opt}_v - \mathrm{alg}_v) \le \sum_{v \in V^{\prime}} (\mathrm{opt}_v - \mathrm{alg}_v) = \mathrm{Loss}
\end{equation}
$$&lt;p&gt;次に，$\mathrm{Loss} \le \mathrm{ALG}$ を示します．$\mathrm{ALG} = \sum_u S_u$ を利用します．&lt;br&gt;
証明しやすいように，$\mathrm{Loss}$ を広告主で分割します．&lt;br&gt;
$V^{\prime}$ のうち最適解で $u$ に割り当てられた広告リクエストの集合を $V^{\prime}_u$ とすると，$\mathrm{Loss}_u = \sum_{v \in V^{\prime}_u} (\mathrm{opt}_v - \mathrm{alg}_v)$ となります．&lt;/p&gt;
&lt;p&gt;$v \in V^{\prime}_u$ が到着したときを考えます．$v$ は最適解では $u$ に，Greedy では $u^{\prime}$ に割り当てられたとします．&lt;br&gt;
$v$ が到着した時点で，Greedy が $u$ ではなく $u^{\prime}$ を選んだということは，その時点での $u$ の修正済み入札額 が $u^{\prime}$ の修正済み入札額以下だったということです．つまり，$u$ の残り予算は高々 $alg_v$ だったということになります．&lt;br&gt;
よって，任意の $v \in V^{\prime}_u$ について $S_u \ge B_u - alg_v$ となります．$B_u$ について整理すると, $B_u \le S_u + \mathrm{alg}_v$ です．&lt;/p&gt;
&lt;p&gt;これまでの議論によって以下が示せます．&lt;/p&gt;
$$
\begin{aligned}
\mathrm{Loss}_u &amp;= \sum_{v \in V^{\prime}_u} (\mathrm{opt}_v - \mathrm{alg}_v) \\
\mathrm{Loss}_u &amp;= \sum_{v \in V^{\prime}_u} \mathrm{opt}_v - \sum_{v \in V^{\prime}_u} \mathrm{alg}_v \\
\mathrm{Loss}_u &amp;\le B_u - \sum_{v \in V^{\prime}_u} \mathrm{alg}_v \\
\mathrm{Loss}_u &amp;\le S_u + \mathrm{alg}_{v} - \sum_{v \in V^{\prime}_u} \mathrm{alg}_v \\
\mathrm{Loss}_u &amp;\le S_u
\end{aligned}
$$&lt;p&gt;3 つ目の式への変形は，$\sum_{v \in V^{\prime}_u} \mathrm{opt}_v \le B_u$ を利用しています．&lt;br&gt;
5 つ目の式への変形は，$V^{\prime}_u = \emptyset$ の場合は $\mathrm{Loss}_u = 0$ が，$V^{\prime}_u \ne \emptyset$ の場合は任意の $v^{\star} \in V^{\prime}_u$ について $\mathrm{alg}_{v^{\star}} \le \sum_{v \in V^{\prime}_u} \mathrm{alg}_v$ が成り立つことを利用しています．
最後の式を $U$ について合計すると，以下の式が成り立ちます．&lt;/p&gt;
$$
\begin{equation}
\mathrm{Loss} = \sum_u \mathrm{Loss}_u \le \sum_u S_u = \mathrm{ALG}
\end{equation}
$$&lt;p&gt;式 (1) と式 (2) から，$\mathrm{OPT} - \mathrm{ALG} \le \mathrm{Loss} = \mathrm{ALG}$ となり，$OPT - ALG \le ALG$ が示せました．&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://research.google/pubs/online-matching-and-ad-allocation/" target="_blank" rel="noopener"
&gt;Online Matching and Ad Allocation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Optimum Branchings の Tarjan の実装</title><link>https://miti-7.github.io/post/optimum-branchings-tarjan/</link><pubDate>Fri, 04 Jul 2025 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/optimum-branchings-tarjan/</guid><description>&lt;img src="https://miti-7.github.io/post/optimum-branchings-tarjan/images/%E5%AE%9F%E8%A1%8C%E4%BE%8B_4_f.png" alt="Featured image of post Optimum Branchings の Tarjan の実装" /&gt;&lt;h2 id="optimum-branchings-の-tarjan-の実装"&gt;Optimum Branchings の Tarjan の実装
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://miti-7.github.io/post/optimum-branchings-edmonds/" target="_blank" rel="noopener"
&gt;Optimum Branchings と Edmonds のアルゴリズム&lt;/a&gt;の続きです．&lt;br&gt;
Tarjan の実装は Edmonds のアルゴリズムを改良し，適切なデータ構造を用いることで計算量を $O(|E| \log |V|)$ に改善したものです．ここで $|E|$ はグラフの辺の数を，$|V|$ は頂点の数を表します．&lt;/p&gt;
&lt;p&gt;Edmonds のアルゴリズムは，クリティカルグラフを作り，クリティカルグラフに閉路が形成されたらその閉路を $1$ つの超頂点に縮約し，縮約したグラフを再帰的に処理していくという流れでした．縮約グラフの最適 branching をもとに，元のグラフ上での対応する辺集合を復元することで最終的な最適 branching を構築します．&lt;/p&gt;
&lt;p&gt;これに対し，Tarjan の実装はおおむね以下のような流れになります．&lt;br&gt;
まだ処理されていない頂点について，その頂点に入る最大の重みを持つ辺を採用します．この辺は最適 branching の構築に必要な構造（森）に記録していきます．もし採用した辺によって閉路が形成された場合，閉路を $1$ つの超頂点に縮約します．その際，閉路の外から閉路に入る辺の重みを修正します．最終的な最適 branching は森から $O(|V|)$ で構築することができます．&lt;br&gt;
Tarjan の実装は，縮約のたびにグラフを再構築することを避け，閉路の展開処理を主アルゴリズムから切り離したことで，計算量を改善しているといえます．&lt;/p&gt;
&lt;p&gt;Tarjan の実装では，「閉路の検出」，「超頂点の管理」，「各頂点に入る辺の管理」が必要です．
これらを効率的に行うために，Union Find と 遅延伝播マージ可能ヒープを使います．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;閉路の検出&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アルゴリズムでは各頂点についてその頂点に入る重み最大の辺を採用していきます．頂点を Union Find で管理し，辺が採用されるたびにその端点をマージしていきます．各頂点は最大でも 1 本の入力辺しかもたないため，採用された辺 $(u, v)$ の $u$ と $v$ が同じ集合なら閉路が形成されたことになります．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;超頂点の管理&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;閉路が超頂点に縮約されたとき，各頂点がどの超頂点に所属しているかを管理する必要があります．これは，Union Find で管理することができます．ただし，この Union Find は閉路の検出用の Union Find とは別でもつ必要があります．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;各頂点に入る辺の管理&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;各頂点に入る辺を管理するデータ構造には，以下の $4$ つの操作が必要です．
&lt;ol&gt;
&lt;li&gt;要素の追加&lt;/li&gt;
&lt;li&gt;最大要素の抽出&lt;/li&gt;
&lt;li&gt;$2$ つの集合のマージ&lt;/li&gt;
&lt;li&gt;集合内の全要素の重みの定数変更&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;これらの操作がすべて対数時間で実行できる場合，Tarjan の実装は $O(|E| \log |V|)$ で動作します．&lt;br&gt;
&lt;a class="link" href="https://en.wikipedia.org/wiki/Skew_heap" target="_blank" rel="noopener"
&gt;Skew Heap&lt;/a&gt; は操作 1, 2, 3 を償却 $O(\log |N|)$ で実行できます．これに遅延伝播機能をつけることで操作 4 を定数時間で実行できます．&lt;/li&gt;
&lt;li&gt;密グラフの場合は，隣接行列を使うことで操作 2, 3, 4 を $O(|V|)$ で実行できます．この場合 Tarjan の実装は $O(|V|^2)$ で動作します．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tarjan-の実装"&gt;Tarjan の実装
&lt;/h2&gt;&lt;p&gt;アルゴリズムは，森 $F$ を構築する Algorithm BRANCH と，森 $F$ から branching を構築する Algorithm LEAF の $2$ つからなります．&lt;br&gt;
森 $F$ は採用された $G$ の辺を頂点とし，縮約過程を親子関係として記録するデータ構造です．&lt;/p&gt;
&lt;h3 id="algorithm-branch"&gt;Algorithm BRANCH
&lt;/h3&gt;&lt;p&gt;このアルゴリズムは，森 $F$ を構築します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;変数&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;S: 強連結成分を管理．はじめ，各頂点がそれぞれ自分だけを要素としてもつ強連結成分となる．&lt;/li&gt;
&lt;li&gt;W: 弱連結成分を管理．はじめ，各頂点がそれぞれ自分だけを要素としてもつ弱連結成分となる．&lt;/li&gt;
&lt;li&gt;$min[v]$: 超頂点 $v$ 内で最終的に根に選ばれる頂点&lt;/li&gt;
&lt;li&gt;$roots$: 入辺のない強連結成分の集合&lt;/li&gt;
&lt;li&gt;$rset$: 正の重みを持つ入辺がない（超）頂点の集合&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$roots$ に要素がある間，以下の処理を繰り返す&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$roots$ から任意の（超）頂点 $r$ を取り出す&lt;/li&gt;
&lt;li&gt;$r$ に入る重みが $0$ より大きい辺がなければ，$r$ を $rset$ に格納する&lt;/li&gt;
&lt;li&gt;そうでなければ，$r$ に入る重み最大の辺 $(u, v)$ を選ぶ&lt;/li&gt;
&lt;li&gt;$(u, v)$ を表す頂点を $F$ に追加する
&lt;ul&gt;
&lt;li&gt;$r$ が超頂点なら，$F$ の $r$ が属する閉路の各頂点を $(u, v)$ の子とする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$u$ と $v$ が異なる弱連結成分に属していれば，$S$ の $2$ つの弱連結成分を結合する&lt;/li&gt;
&lt;li&gt;そうでなければ閉路が発生する
&lt;ul&gt;
&lt;li&gt;$C$ を $(u, v)$ を含む閉路とする&lt;/li&gt;
&lt;li&gt;$W$ で $C$ に含まれるすべての強連結成分を $1$ つの超頂点 $r^{\prime}$ に縮約する&lt;/li&gt;
&lt;li&gt;$C$ に含まれる最小重みの辺の行き先を $m$ とし，$min[r^{\prime}] = m$ とする&lt;/li&gt;
&lt;li&gt;$r^{\prime}$ に外部から入る辺の重みを更新する&lt;/li&gt;
&lt;li&gt;$r^{\prime}$ を $roots$ に追加する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="algorithm-leaf"&gt;Algorithm LEAF
&lt;/h3&gt;&lt;p&gt;Algorithm LEAF は $F$ から最適 branching $B$ を構築します．&lt;br&gt;
$R = \lbrace min(i) | i \in rset \rbrace$，$N$ を $F$ の根の集合とします．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$R$ が空でないなら，$R$ から $v$ を 1 つ取り出す&lt;br&gt;
$R$ が空の場合は，$N$ から任意の根 $(u,v)$ を選び $B$ に追加し，$v$ を処理対象とする&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$F$ の $v$ に入る辺を表す頂点から根までのパス $P$ を特定する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$F$ からパス $P$ 上のすべての頂点およびそれらから出る全ての辺を削除する&lt;br&gt;
この削除操作により，$N$ も更新される&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;この一連の処理を $R$ と $N$ がともに空になるまで繰り返すと，最適 branching $B$ が構築されます．&lt;/p&gt;
&lt;h2 id="アルゴリズムの実行例"&gt;アルゴリズムの実行例
&lt;/h2&gt;&lt;p&gt;下のグラフの branching を求めます．&lt;br&gt;
&lt;img src="images/実行例_0.png" width="25%"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="phase1"&gt;phase1
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;頂点 $0$ に入る重み最大の辺 $(2, 0)$ を選びます．森 $F$ に $2 \rightarrow 0$ を表す頂点を追加します．&lt;/li&gt;
&lt;li&gt;同様に，頂点 $1$，$2$ に入る重み最大の辺 $(0, 1), (1, 2)$ を $F$に追加します&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;．
閉路 $0 \rightarrow 1 \rightarrow 2 \rightarrow 0$ が見つかったので，これを超頂点 $A$ に縮約します．
$(3, 1)$ の重みを $4 - 4 + 3 = 3$ に変更します．&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="heading"&gt;&lt;img src="images/実行例_1.png" width="25%"&gt; &lt;img src="images/実行例_1_f.png" width="25%"&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id="phase2"&gt;phase2
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;頂点 $A$ に入る重み最大の辺 $(3, A)$ を選びます．$F$ に $3 \rightarrow A$ を追加します．&lt;br&gt;
$(3, A)$ は超頂点 $A$ に入る辺なので，$3 \rightarrow A$ が親となるように $2 \rightarrow 0$，$0 \rightarrow 1$，$1 \rightarrow 2$ に辺をはります．&lt;/li&gt;
&lt;li&gt;頂点 $3$ に入る重み最大の辺 $(A, 3)$ を選び，$F$ に追加します．&lt;br&gt;
閉路 $A \rightarrow 3 \rightarrow A$ が見つかったので，これを超頂点 $B$ に縮約します．&lt;br&gt;
$(4, A)$ の重みを $1 - 3 + 3 = 1$ に変更します．&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="heading-1"&gt;&lt;img src="images/実行例_2.png" width="25%"&gt; &lt;img src="images/実行例_2_f.png" width="25%"&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id="phase3"&gt;phase3
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;頂点 $B$ に入る重み最大の辺 $(4, B)$ を選びます．$F$ に $4 \rightarrow B$ を追加します．&lt;br&gt;
$(4, B)$ は超頂点 $B$ に入る辺なので，$4 \rightarrow B$ から $3 \rightarrow A$，$A \rightarrow 3$ に辺をはります．&lt;/li&gt;
&lt;li&gt;頂点 $4$，$5$ に入る重み最大の辺 $(5, 4)$，$(B, 5)$ を選び，$F$ に追加します．&lt;br&gt;
閉路 $B \rightarrow 5 \rightarrow 4 \rightarrow B$ が見つかったので，これを超頂点 $C$ に縮約します．&lt;br&gt;
$(6, 4)$ の重みを $4 - 4 + 1 = 1$ に変更します．&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="heading-2"&gt;&lt;img src="images/実行例_3.png" width="25%"&gt; &lt;img src="images/実行例_3_f.png" width="25%"&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id="phase4"&gt;phase4
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;頂点 $C$ に入る重み最大の辺 $(6, C)$ を選びます．$F$ に $6 \rightarrow C$ を追加します．&lt;br&gt;
$(6, C)$ は超頂点 $C$ に入る辺なので，$6 \rightarrow C$ から $4 \rightarrow B$，$5 \rightarrow 4$，$B \rightarrow 5$ に辺をはります．&lt;/li&gt;
&lt;li&gt;頂点 $6$ に入る重み最大の辺 $(C, 6)$ を選び，$F$ に追加します．&lt;br&gt;
閉路 $C \rightarrow 6 \rightarrow C$ が見つかったので，これを超頂点 $D$ に縮約します．&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="heading-3"&gt;&lt;img src="images/実行例_4.png" width="25%"&gt; &lt;img src="images/実行例_4_f.png" width="25%"&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id="phase5"&gt;phase5
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;頂点 $D$ に入る辺はないので，Algorithm BRANCH は終了します．&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="heading-4"&gt;&lt;img src="images/実行例_5.png" width="25%"&gt; &lt;img src="images/実行例_4_f.png" width="25%"&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id="phase6"&gt;phase6
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;森 $F$ が求められたので，最適 branching $B$ を構築していきます．&lt;/li&gt;
&lt;li&gt;$R = \lbrace 5 \rbrace$ から $5$ を取り出します．&lt;/li&gt;
&lt;li&gt;$5$ に入る辺である $B \rightarrow 5$ から根までのパス $P$ を求め，これを削除します．&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=""&gt;&lt;img src="images/実行例_6.png" width="25%"&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id="phase7"&gt;phase7
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;森の根である $C \rightarrow 6$ を取り出し，$B$ の辺として採用します．$C \rightarrow 6$ は実際には，$5 \rightarrow 6$ なので，$B$ では $(5, 6)$ を採用しています．&lt;br&gt;
$6$ に入る辺は森にないので，パス $P$ の削除は行われません．&lt;/li&gt;
&lt;li&gt;森の根である $5 \rightarrow 4$ も同様に処理をします．&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="heading-5"&gt;&lt;img src="images/実行例_7.png" width="25%"&gt; &lt;img src="images/実行例_7_g.png" width="25%"&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id="phase8"&gt;phase8
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;森の根である $4 \rightarrow B$ を取り出し，$B$ の辺として採用します．$4 \rightarrow B$ は実際には，$4 \rightarrow 2$ なので，$B$ では $4 \rightarrow 2$ を採用しています．&lt;br&gt;
根から $2$ に入る辺である $1 \rightarrow 2$ までのパスを求め削除します．&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="heading-6"&gt;&lt;img src="images/実行例_8.png" width="25%"&gt; &lt;img src="images/実行例_8_g.png" width="25%"&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id="phase9"&gt;phase9
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;森の根である $A \rightarrow 3$，$2 \rightarrow 0$，$0 \rightarrow 1$ を処理します．&lt;/li&gt;
&lt;li&gt;森のすべての要素を処理したのでアルゴリズムを終了します．&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="heading-7"&gt;&lt;img src="images/実行例_9.png" width="25%"&gt; &lt;img src="images/実行例_9_g.png" width="25%"&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h2 id="問題"&gt;問題
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://judge.yosupo.jp/problem/directedmst" target="_blank" rel="noopener"
&gt;Directed MST&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://judge.yosupo.jp/submission/296045" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://onlinelibrary.wiley.com/doi/10.1002/net.3230070103" target="_blank" rel="noopener"
&gt;Finding optimum branchings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://onlinelibrary.wiley.com/doi/10.1002/net.3230090403" target="_blank" rel="noopener"
&gt;A note on finding optimum branchings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cw.fel.cvut.cz/old/_media/courses/a4m33pal/cviceni/algorithm-description.pdf" target="_blank" rel="noopener"
&gt;Optimum Branchings and Spanning Aborescences&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/abs/2208.02590" target="_blank" rel="noopener"
&gt;Efficiently Computing Directed Minimum Spanning Trees&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;$(3, 1)$ も $1$ に入る重み最大の辺ですが，ここでは $(0, 1)$ を選んだとします．&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Optimum Branchings と Edmonds のアルゴリズム</title><link>https://miti-7.github.io/post/optimum-branchings-edmonds/</link><pubDate>Fri, 20 Jun 2025 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/optimum-branchings-edmonds/</guid><description>&lt;img src="https://miti-7.github.io/post/optimum-branchings-edmonds/images/branching%E3%81%AE%E4%BE%8B.png" alt="Featured image of post Optimum Branchings と Edmonds のアルゴリズム" /&gt;&lt;h2 id="optimum-branchings"&gt;Optimum Branchings
&lt;/h2&gt;&lt;p&gt;有向グラフ $G = (V, E)$ が与えられます．各辺には重みが与えられ，辺 $e$ の重みと辺集合の重みをそれぞれ $w(e)$, $w(E)$ で表します．&lt;br&gt;
$G$ の部分グラフ $G^{\prime} = (V, E^{\prime})$ のうち以下の 2 条件を満たすものを branching とよびます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;閉路を含まない&lt;/li&gt;
&lt;li&gt;同じ頂点に入る辺は高々 $1$ 本&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;すべての branching の中で $w(E^{\prime})$ が最大のものを 最適 branching（optimum branching）とよびます&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;．&lt;br&gt;
この問題は，最小全域木問題の有向辺バージョンである最小全域有向木問題と等価の問題で，互いに線形時間で変換することができます．&lt;br&gt;
下の図は有向グラフと対応する 最適 branching の例です．$G^{\prime}$ の各コンポーネントは有向木なので，$G^{\prime}$は有向森になります．&lt;/p&gt;
&lt;img src="images/branchingの例.png" width="50%"&gt;
&lt;p&gt;以下ではいくつかの定義，補題，定理を確認したのち，最適 branching を求める Edmonds のアルゴリズムを説明します．&lt;br&gt;
このアルゴリズムの計算量は $O(|E||V|)$ です．他にも $O(|E| \log |V|)$ の Tarjan の実装や $O(|E| + |V| \log |V|)$ の Gabow のアルゴリズムなどがあります．&lt;br&gt;
また，最小重み有向木問題などのバリエーションを最適 Branching に帰着する方法と説明します．&lt;br&gt;
最後に実装例として&lt;a class="link" href="https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_2_B" target="_blank" rel="noopener"
&gt;AOJ - 最小全域有向木&lt;/a&gt;の提出コードへのリンクをはっておきます．&lt;/p&gt;
&lt;h2 id="定義"&gt;定義
&lt;/h2&gt;&lt;h3 id="critical"&gt;critical
&lt;/h3&gt;&lt;p&gt;辺 $e = (u, v)$ が以下の 2 条件を満たすとき critical という．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$w(e) \gt 0$&lt;/li&gt;
&lt;li&gt;$v$ に接続するすべての辺 $e^{\prime}$ に対して，$w(e) \ge w(e^{\prime})$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$G$ の全域部分グラフ $H$ が以下の条件を満たすとき critical subgraph という．特にそれ以上辺を追加できない critical subgraph を maximal critical subgraph という．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$H$ のすべての辺は critical&lt;/li&gt;
&lt;li&gt;$H$ の各頂点の入次数は高々 $1$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下の図は maximal critical subgraph の例です．critical な辺を赤線で示しています．&lt;/p&gt;
&lt;img src="images/maximal_critical_subgraph.png" width="25%"&gt;
&lt;h3 id="eligible"&gt;eligible
&lt;/h3&gt;&lt;p&gt;辺 $e$ が入る頂点を $head(e)$ と表す．$G = (V, E)$ の branching $B$ に対して，$(B \backslash \lbrace (u, v) \in B : v = head(e) \rbrace) \cup \lbrace e \rbrace$ も branching になるとき，$e$ を eligible という．&lt;/p&gt;
&lt;h2 id="補題-1"&gt;補題 1
&lt;/h2&gt;&lt;p&gt;maximal critical subgraph $H$ は以下の性質を持ちます．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;各コンポーネントは高々 1 つの閉路をもち，閉路は互いに素&lt;/li&gt;
&lt;li&gt;$H$ に閉路がなければ最適 branching&lt;/li&gt;
&lt;/ol&gt;
&lt;details&gt;&lt;summary&gt;証明&lt;/summary&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;頂点 $v$ が $2$ つの有向閉路上にあるとします．このとき，次数が少なくとも $2$ 以上の頂点が存在します．これは critical subgraph の条件に反します．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$H$ に閉路がなければ $H$は branching です．任意の branching $B$ のすべての頂点 $v$ について以下が成り立ちます．&lt;br&gt;
$w(B \cap \lbrace e | head(e) = v \rbrace) \le w(H \cap \lbrace e | head(e) = v \rbrace)$&lt;br&gt;
これらをすべての頂点について足し合わせると $w(B) \le w(H)$ となり，$H$ が最適となります．&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;/details&gt;
&lt;h2 id="補題-2"&gt;補題 2
&lt;/h2&gt;&lt;p&gt;辺 $e = (u, v) \in E \backslash B$ が eligible なことと，$B$ 上に $v$ から $u$ への有向パスがないことは同値&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;証明&lt;/summary&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;「辺 $e = (u, v) \in E \backslash B$ が eligible」なら「$B$ 上に $v$ から $u$ への有向パスがない」&lt;br&gt;
対偶として，$v$ から $u$ への有向パスがあるなら，$e$ は eligible ではないことを示します．&lt;br&gt;
$v$ から $u$ への有向パスがあるため，$(u, v)$ を追加すると閉路が発生します．&lt;br&gt;
これは eligible の定義に反するため，$e$ は eligible ではありません．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;「$B$ 上に $v$ から $u$ への有向パスがない」なら「辺 $e = (u, v) \in E \backslash B$ が eligible」&lt;br&gt;
$e$ を $B$ に追加したとき，$(x, head(e)) \in B$ の辺を削除すれば $v$ へ入る辺は高々 $1$ 本です．&lt;br&gt;
また，$B$ には $v \rightarrow u$ パスがないので，$e$ を追加しても閉路は発生しません．&lt;br&gt;
よって，$e$ は eligible です．&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;/details&gt;
&lt;h2 id="補題-3"&gt;補題 3
&lt;/h2&gt;&lt;p&gt;$B$ を $G = (V, E)$ の branching，$C$ を $G$ の有向サイクルとする．$C \backslash B$ に eligible な辺がなければ， $|C \backslash B| = 1$ となる&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;証明&lt;/summary&gt;
&lt;p&gt;$C \backslash B$ に eligible な辺がないとき，$|C \backslash B|$ は 1 以外にならないことを示します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$|C \backslash B| = 0$ にならない&lt;br&gt;
$B$ は branching なので起こりません&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$|C \backslash B| = 2$ にならない&lt;br&gt;
$C \backslash B = \lbrace (s_1, t_1), (s_2, t_2) \rbrace$ と仮定します．&lt;br&gt;
どちらの辺も eligible でないので，$B$ に $t_1$ から $s_1$ への有向パスと $t_2$ から $s_2$ への有向パスが存在します．&lt;br&gt;
$C$ は閉路なので，$t_2$ から $s_1$ への有向パスと $t_1$ から $s_2$ への有向パスは $C$ 上に存在します．&lt;br&gt;
よって，$B$ には，$t_2 \rightarrow \cdots \rightarrow \cdots s_1 \rightarrow t_1 \rightarrow \cdots \rightarrow s_2 \rightarrow t_2$ のようなパスができます．&lt;br&gt;
これは，$B$ の中に閉路があるということになり，$B$ が branching という仮定に矛盾します．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$|C \backslash B| = k \gt 2$ にならない&lt;br&gt;
$|C \backslash B| = 2$ に帰着します．&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id="定理-1"&gt;定理 1
&lt;/h2&gt;&lt;p&gt;$G$ の maximal critical subgraph $H$ に対し，以下の最適 branching $B$ が存在する．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$H$ に含まれるすべての有向閉路 $C_i$ について，$| C_i \backslash B| = 1$．&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;つまり，$H$ の各有向閉路からちょうど $1$ 本だけ辺が取り除かれているような最適 branching が存在するということです．&lt;br&gt;
下の図は $G$ に対する maximul critical subgraph $H$ と最適 branching です．&lt;br&gt;
$H$ の閉路から $(0, 1)$ と $(3, 5)$ を取り除いた最適 branching が存在することがわかります．&lt;/p&gt;
&lt;img src="images/theorem1_0.png" width="50%"&gt;
&lt;details&gt;&lt;summary&gt;証明&lt;/summary&gt;
&lt;hr&gt;
&lt;p&gt;最適 branching のうち，$H$ の辺を最も多く含んでいるものを $B$ と仮定します．&lt;br&gt;
補題 2 により，$C \backslash B$ に eligible な辺がなければ，$|C \backslash B| = 1$ となるので，各 $C_i \backslash B$ のすべての辺が eligible でないことを示します．&lt;br&gt;
$e \in H \backslash B$ が eligible であると矛盾が起きることを示します．&lt;br&gt;
$e$ は eligible なので，新しい branching $B^{\prime} = \lbrace B \backslash \lbrace e^{\prime} \rbrace \rbrace \cup \lbrace e \rbrace$ を作ることができます．ここで $e^{\prime}$ は，$head(e)$ に入る $B$ 上の辺です．&lt;br&gt;
このとき，$e \in H$ であり，$e^{\prime} \notin H$ であるため，$B^{\prime}$ は $B$ より多くの $H$ の辺を含みます．&lt;br&gt;
また，$e$ は critical なので，$B^{\prime}$ は最適 branching です．&lt;br&gt;
よって，$B$ より$H$ の辺を多く含む最適 branching $B^{\prime}$ ができることとなり，これは仮定に矛盾します．&lt;/p&gt;
&lt;hr&gt;
&lt;/details&gt;
&lt;h2 id="定理-2"&gt;定理 2
&lt;/h2&gt;&lt;p&gt;定理 1 を満たすような最適 branching $B$ に，以下の条件を満たす解が存在する．ここで $e^{0}_i$ は $C_i$ で最も重みの小さい辺である．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;各有向閉路 $C_i$ で $|C_i \backslash B| = 1$&lt;/li&gt;
&lt;li&gt;もし有向閉路 $C_i$ へ外部から入る辺が $B$ に存在しないなら，$C_i \backslash B = \lbrace e^{0}_i \rbrace$ である．&lt;/li&gt;
&lt;/ol&gt;
&lt;details&gt;&lt;summary&gt;証明&lt;/summary&gt;
&lt;hr&gt;
&lt;p&gt;1.を満たす最適 branching の中で，$\lbrace e^{0}_0, e^{1}_0, \cdots, e^{0}_k \rbrace$ が含まれる数がもっとも多いものを $B$ とします．&lt;br&gt;
$B$ には $C_i$ に外部から入る辺が存在しないにも関わらず，$C_i$ に $e^{0}_i$ が含まれていると仮定します．&lt;br&gt;
$C_i \backslash B = \lbrace e \rbrace$ とします．&lt;br&gt;
$B^{\prime} = (B \backslash \lbrace e^{0}_i \rbrace) \cup \lbrace e \rbrace$ とします．&lt;br&gt;
この $B^{\prime}$ は $\lbrace e^{0}_i \rbrace$ を含む最適 branching です．
これは仮定と矛盾します．&lt;/p&gt;
&lt;hr&gt;
&lt;/details&gt;
&lt;h2 id="edmonds-のアルゴリズム"&gt;Edmonds のアルゴリズム
&lt;/h2&gt;&lt;p&gt;グラフ $G = (V, E)$ の最適 branching を求める方法を考えます．表記上の都合のため多重辺はないものとします&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;．&lt;/p&gt;
&lt;p&gt;まず，maximal critical subgraph を求め，この辺集合を $H$ とします．&lt;br&gt;
補題 1 により $(V, H)$ が branching なら $(V, H)$ は最適 branching です．&lt;/p&gt;
&lt;p&gt;$(V, H)$ が branching でない場合を考えます．&lt;br&gt;
この場合，$(V, H)$ には有向閉路が 1 つ以上存在します．&lt;br&gt;
定理 1 により，各閉路から 1 本辺を削除した辺集合を含む最適 branching $B^{\star}$ が存在することがわかります．今後はこの $B^{\star}$ を求めていきます．&lt;/p&gt;
&lt;p&gt;$B^{\star}$ を求めるためには maximal critical graph の各閉路のどの辺を削除すればいいのかを考ます．&lt;br&gt;
もし，$B^{\star}$ に（閉路の）外部から閉路に入る辺 $(u, v)$ がある場合，$v$ の入次数が $2$ になるのを避けるために閉路内で $v$ に入る辺を削除することになります．反対に，外部から閉路に入る辺がない場合，定理 2 より閉路内で最小の辺を削除することになります．&lt;br&gt;
つまり，閉路のどの辺を削除するかは閉路外部の辺構造によって決めることができます．そこで，閉路内部の辺構造（つまり，どの辺を削除するのか）を決めるより先に外部の辺構造を決めてしまいます．&lt;br&gt;
そのために，閉路外部の重みを適切に調整した上で閉路を $1$ つの超頂点に縮約します．この手続きによって得られるグラフを $G^{\prime} = (V^{\prime}, E^{\prime})$ とします．&lt;br&gt;
この $G^{\prime}$ の最適 branching に超頂点に入る辺があるかどうかによって，$H$ の閉路のどの辺を削除するかを決めることができます．&lt;/p&gt;
&lt;p&gt;$G^{\prime}$ の辺の重み $w^{\prime}$ をどう設定するかを考えます．&lt;br&gt;
$G^{\prime}$ の最適 branching から構成した $G$ の branching も最適 branching であるという条件を満たす必要があります．&lt;br&gt;
このためには，任意の branching について，$w(B) = w^{\prime}(B^{\prime}) + const$ であることを示せればいいです．$B^{\prime}$ と $B$ の重みの差は定数なので，$B^{\prime}$ が最適なら $B$ も最適といえるためです．&lt;br&gt;
外部から閉路に入る辺を $e = (u, v)$，$v$ に入る閉路内唯一の辺を $\tilde e$，閉路の最小の重みを持つ辺を $e^{0}$ とします．
この条件を満たすためには，閉路に入る辺 $e$ の重みを $w^{\prime}(e) = w(e) - w(\tilde e) + w(e^{0})$ と設定すればいいです．&lt;br&gt;
閉路に入る辺以外の重みは $w$ のままとします．&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;証明&lt;/summary&gt;
&lt;hr&gt;
&lt;p&gt;$w(B) = w^{\prime}(B^{\prime}) + const$ となることを示します．&lt;br&gt;
$B^{\prime}$ の超頂点を展開したときの重みの増加分を考えます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;超頂点に入る辺 $e$ がないとき&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$e^{0}_i$ 以外の辺を採用するので，$w(C_i) - w(e^{0}_i)$ だけ増加します．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;超頂点に入る辺 $e$ があるとき&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$w(\tilde e)$ 以外の辺を採用するので，$w(C_i) - w(\tilde e)$ だけ増加します．&lt;br&gt;
ただし，$e$ の重みを $w^{\prime}(e) = w(e) - w(\tilde e) + w(e^{0}_i)$ と調整していたので，この調整を打ち消すと $w(C_i) - w(\tilde e) - (- w(\tilde e) + w(e^{0}_i)) = w(C_i) - w(e^{0}_i)$ となります．&lt;br&gt;
結局，$w(C_i) - w(e^{0}_i)$ だけ増加します．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;よって，どちらも $w(C_i) - w(e_i^{0})$ だけ増加するので，すべての閉路についてこの和をとると $w(B) = w^{\prime}(B^{\prime}) + \sum_{i} w(C_i) - \sum_{i} w(e_i^{0})$ となります．&lt;br&gt;
$\sum_{i} w(C_i) - \sum_{i} w(e^{0}_i)$ の部分は branching のとり方に依存しないため定数とみなすことができ，$w(B) = w^{\prime}(B^{\prime}) + const$ となります．&lt;/p&gt;
&lt;hr&gt;
&lt;/details&gt;
&lt;p&gt;このように重みを設定した $G^{\prime}$ に対し，最適 branching を求める手続きを再帰的に実行します．&lt;br&gt;
$G^{\prime}$ は元のグラフより厳密に頂点数が少なくなるため，この手続きは有限回で終了します．&lt;/p&gt;
&lt;p&gt;$G$ の最適 branching $B$ は，この再帰呼び出しから返される $G^{\prime}$ の最適 branching $B^{\prime}$ に対して，閉路の $1$ 本を除いた残りすべての辺を加えることにより構築することができます．&lt;/p&gt;
&lt;p&gt;最後に計算量について考えます．&lt;br&gt;
1 回の手続きで少なくとも 1 つの頂点が減ります．1 回の手続きには $O(|E|)$ かかるので，このアルゴリズムの計算量は $O(|E||V|)$ です．&lt;/p&gt;
&lt;h2 id="edmonds-のアルゴリズムまとめ"&gt;Edmonds のアルゴリズムまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;step 1: maximal critical subgraph の構築
maximal critical subgraph を求めます．この辺の集合を $H$ とします．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;step 2: 閉路のチェック&lt;br&gt;
$(V, H)$ が branching を形成する場合，$(V, H)$ が最適 branching であるため，これを返します．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;step 3: 閉路の縮約&lt;br&gt;
$H$ が $1$ つ以上の閉路を含む場合，任意の閉路 $C$ を選び，$C$ を $1$ つの超頂点 $a$​ に縮約します．&lt;br&gt;
この操作によってできたグラフを $G^{\prime} = (V^{\prime}, E^{\prime})$とします．ここで，$V^{\prime} = (V \backslash C) \cup a$ です．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;step 4: $G^{\prime}$ における辺の重みの変更&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$C$ に入る辺：
&lt;ul&gt;
&lt;li&gt;辺 $(u \notin C, v \in C)$ に対して、$G^{\prime}$ 内の新しい辺 $(u, a​)$ の重み $w^{\prime}(u, a)$ を $w(u, v) - w(\tilde e) + w(e^{0})$ とします．ここで，$w(\tilde e)$ は $C$ に存在する頂点 $v$ に入る辺の重み，$w(e^{0})$ は $C$ に存在する辺の最小の重みです．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$C$ から出る辺：
&lt;ul&gt;
&lt;li&gt;辺 $(u \in C, v \notin C)$ に対して、$G^{\prime}$ 内の新しい辺 $(a, v)$ の重み $w^{\prime}(a​, v)$ を $w(u, v)$ とします．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$C$ に無関係な辺：
&lt;ul&gt;
&lt;li&gt;辺 $(u \notin C,v \notin C)$ に対して、$(u, v​)$ の重み $w^{\prime}(u, v​)$ を $w(u, v)$ とします．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;step 5: 再帰呼び出し&lt;br&gt;
$G^{\prime}$ の最適 branching を再帰的に見つけます．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;step 6: 展開&lt;br&gt;
$G^{\prime}$ の最適 branching が，閉路の外から超頂点 $a$​ に入る辺を持つ場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;超頂点を展開します．$a$ に入る辺が展開後 $(u, v)$ であったとします．$C$ に含まれる辺のうち $v$ に入る辺以外の $|C| - 1$ 本を採用します．このようにして選んだ辺集合は最適 branching であるため，これを返します．&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$G^{\prime}$ の最適 branching が，閉路の外から超頂点 $a$​ に入る辺を持たない場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;超頂点を展開します．$C$ に含まれる辺のうち，最小の重みの辺以外の $|C| - 1$本を採用します．このようにして選んだ辺集合は最適 branching であるため，これを返します．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="アルゴリズムの実行例"&gt;アルゴリズムの実行例
&lt;/h2&gt;&lt;p&gt;下のグラフの branching を求めます．&lt;/p&gt;
&lt;img src="images/edmonds_0.png" width="25%"&gt;
&lt;hr&gt;
&lt;h3 id="phase1"&gt;phase1
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;maximal critical subgraph を求めます．図では赤色の辺が対応します．&lt;/li&gt;
&lt;li&gt;閉路のチェック
&lt;ul&gt;
&lt;li&gt;$(2, 5), (5, 4), (4, 2)$ によって閉路が生じます．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;閉路の縮約
&lt;ul&gt;
&lt;li&gt;閉路に属する頂点 $\lbrace 2, 4, 5 \rbrace$ を超頂点 $6$ に縮約します．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;辺の重みの変更
&lt;ul&gt;
&lt;li&gt;超頂点に入る辺 $(0, 2)$ の重みを変更します．$2$ に入る閉路の辺の重みは $5$，閉路最小の重みは $4$ なので，$2 - 5 + 4 = 1$ となります．&lt;/li&gt;
&lt;li&gt;超頂点に入る辺 $(3, 4)$ の重みを変更します．$4$ に入る閉路の辺の重みは $4$，閉路最小の重みは $4$ なので，$3 - 4 + 4 = 3$ となります．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;再帰呼び出し
&lt;ul&gt;
&lt;li&gt;新しくできたグラフの最適 branching を求めます．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/edmonds_1.png" width="50%"&gt;
&lt;hr&gt;
&lt;h3 id="phase2"&gt;phase2
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;maximal critical subgraph を求めます．&lt;/li&gt;
&lt;li&gt;閉路のチェック
&lt;ul&gt;
&lt;li&gt;$(1, 3), (3, 6), (6, 1)$ によって閉路が生じます．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;閉路の縮約
&lt;ul&gt;
&lt;li&gt;閉路に属する頂点 $\lbrace 1, 3, 6 \rbrace$ を超頂点 $7$ に縮約します．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;辺の重みの変更
&lt;ul&gt;
&lt;li&gt;超頂点に入る辺 $(0, 6)$ の重みを変更します．$6$ に入る閉路の辺の重みは $3$，閉路最小の重みは $1$ なので，$1 - 3 + 1 = -1$ となります．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;再帰呼び出し
&lt;ul&gt;
&lt;li&gt;新しくできたグラフの最適 branching を求めます．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/edmonds_2.png" width="50%"&gt;
&lt;hr&gt;
&lt;h3 id="phase3"&gt;phase3
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;maximal critical subgraph を求めます．&lt;/li&gt;
&lt;li&gt;閉路のチェック
&lt;ul&gt;
&lt;li&gt;閉路が存在しないため，これは最適 branching です．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/edmonds_3.png" width="25%"&gt;
&lt;hr&gt;
&lt;h3 id="phase4"&gt;phase4
&lt;/h3&gt;&lt;p&gt;ここからは閉路の展開をしていきます．&lt;br&gt;
現在は，$(7, 0)$ が branching の辺として選ばれています．&lt;br&gt;
branching として選ばれた辺は青色の辺で示していきます．&lt;br&gt;
&lt;img src="images/edmonds_4.png" width="25%"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="phase5"&gt;phase5
&lt;/h3&gt;&lt;p&gt;超頂点 $7$ を展開します．超頂点 $7$ は $(1, 3), (3, 6), (6, 1)$ からなる閉路でした．&lt;br&gt;
この閉路に入る辺はないので，閉路のなかで最小の辺 $(6, 1)$ を除外し，$(1, 3), (3, 6)$ を採用します．
&lt;img src="images/edmonds_5.png" width="50%"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="phase6"&gt;phase6
&lt;/h3&gt;&lt;p&gt;超頂点 $6$ を展開します．超頂点 $6$ は $(2, 5), (5, 4), (4, 2)$ からなる閉路でした．&lt;br&gt;
この閉路には $(3, 4)$ が入るので，閉路の中で $4$ に入る $(5, 4)$ を除外し，$(2, 5), (4, 2)$ を採用します．&lt;br&gt;
すべての閉路を展開をしたので，アルゴリズムを終了します．&lt;br&gt;
&lt;img src="images/edmonds_6.png" width="50%"&gt;&lt;/p&gt;
&lt;h2 id="問題のバリエーション"&gt;問題のバリエーション
&lt;/h2&gt;&lt;p&gt;以下の問題は，optimal branching と等価の問題であり，最適 branching のアルゴリズムを使って解くことができます．&lt;/p&gt;
&lt;h3 id="最小重み有向木問題minimum-weight-arborescence-problem"&gt;最小重み有向木問題（Minimum Weight Arborescence Problem）
&lt;/h3&gt;&lt;p&gt;$G = (V, E)$ の全域有向森ではなく，全域有向木を求める問題です．木の根は任意になります．&lt;br&gt;
$G$ に全域有向木が存在すると仮定します．&lt;br&gt;
$G = (V, E)$ に対し，$K = 1 + \sum_{e \in E} |w(e)|$ とします．&lt;br&gt;
$w^{\prime}(e) = K - w(e)$ と重みを変更した $G$ で最適 branching 問題を解きます．&lt;/p&gt;
&lt;p&gt;木 $B$ の辺の数を $|B|$ と表します．$|B| \gt |B^{\prime}|$ である任意の $2$ つの有向木 $B$，$B^{\prime}$ に対して，$w^{\prime}(B) - w^{\prime}(B^{\prime}) = (|B| - |B^{\prime}|)K - (w(B) - w(B^{\prime})) \ge 0$ が成り立ちます．&lt;br&gt;
よって，$|B| \gt |B^{\prime}|$ ならば $w^{\prime}(B) \gt w^{\prime}(B^{\prime})$ であるため，最小重み有向木問題の解を求めることができます．&lt;/p&gt;
&lt;h3 id="最小重み根指定有向木問題minimum-weight-rooted-arborescence-problem"&gt;最小重み根指定有向木問題（Minimum Weight Rooted Arborescence Problem）&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;
&lt;/h3&gt;&lt;p&gt;最小重み有向木問題で，全域木の根 $r$ が指定されている問題です．&lt;br&gt;
$G$ に $r$ を根とする全域有向木が存在すると仮定します．&lt;br&gt;
超頂点 $s$ を用意し，$G^{\prime} = (V(G) \cup \lbrace s \rbrace, E \cup \lbrace (s, r) \rbrace)$，$w(s, r) = 0$ とします．&lt;br&gt;
$G^{\prime}$ に対し，最小重み有向木問題の解を求め，$s$ を削除することで，最小重み根指定有向木問題の解を得ることができます．&lt;/p&gt;
&lt;h2 id="問題"&gt;問題
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_2_B" target="_blank" rel="noopener"
&gt;AOJ - 最小全域有向木&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=10616122#1" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://en.wikipedia.org/wiki/Edmonds%27_algorithm" target="_blank" rel="noopener"
&gt;Edmonds&amp;rsquo; algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://users-math.au.dk/jensen/teaching/2018GraphTheory2/notes.pdf" target="_blank" rel="noopener"
&gt;Lecture notes: Graph Theory 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://faculty.fiu.edu/~ramsamuj/graphtheory/chap3.pdf" target="_blank" rel="noopener"
&gt;GRAPH THEORY 3. Trees&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.taylorfrancis.com/books/mono/10.1201/b19163" target="_blank" rel="noopener"
&gt;Handbook of Graph Theory, Combinatorial Optimization, and Algorithms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.maruzen-publishing.co.jp/book/b10121874.html" target="_blank" rel="noopener"
&gt;組合せ最適化&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://www.maruzen-publishing.co.jp/book/b10121874.html" target="_blank" rel="noopener"
&gt;組合せ最適化&lt;/a&gt;では最大重み有向森問題（Maximum Weight Branching Problem）と表記されています&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;重みが最小の branching を求めたいときは重みの正負を反転します&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;辺を $(u, v)$ と表記したときに，一意に定めるためです&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;最小全域有向木問題，最小有向木問題とも&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Primal Dual Algorithm(厳密解)</title><link>https://miti-7.github.io/post/primal-dual-algorithm%E5%8E%B3%E5%AF%86%E8%A7%A3/</link><pubDate>Fri, 14 Mar 2025 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/primal-dual-algorithm%E5%8E%B3%E5%AF%86%E8%A7%A3/</guid><description>&lt;h2 id="はじめに"&gt;はじめに
&lt;/h2&gt;&lt;p&gt;厳密解を求める primal dual algorithm の話です．&lt;br&gt;
primal dual algorithm の一般的な説明をしたあと，具体例としてハンガリアン法を導出します．&lt;/p&gt;
&lt;h2 id="準備"&gt;準備
&lt;/h2&gt;&lt;p&gt;以下の等式標準形の線形計画問題を考えます．簡単のため $\bold b \ge 0$ を仮定します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;主問題&lt;/p&gt;
$$
\begin{aligned}
&amp;\text{minimize} &amp;&amp; \bold c^{T} \bold x \\
&amp;\text{subject to}
&amp;&amp; \bold A \bold x = \bold b \\
&amp; &amp;&amp; \bold x \geq 0
\end{aligned}
$$&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;双対問題
&lt;/p&gt;
$$
\begin{aligned}
&amp;\text{maxiimize} &amp;&amp; \bold b^{T} \bold y \\
&amp;\text{subject to}
&amp;&amp; \bold A^{T} \bold y \leq \bold c
\end{aligned}
$$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$\bold x$ と $\bold y$ が主問題と双対問題の最適解であるための必要十分条件は，以下の 2 つの条件をともに満たすことです．&lt;br&gt;
$A_i$ は行列 $\bold A$ の $i$行目を，$A^{j}$ は行列 $\bold A$ の $j$ 列目の転置をとったものを表します．今回は主問題の制約条件に $\bold A \bold x = \bold b$ があるため，双対相補性条件を常に満たします．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;主相補性条件&lt;/p&gt;
$$
\begin{aligned}
&amp;&amp; x_{j} \gt 0 \Rightarrow \bold A^{j} \bold y = c_{j} &amp;&amp;&amp; \forall j \\
\end{aligned}
$$&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;双対相補性条件
&lt;/p&gt;
$$
\begin{aligned}
&amp;&amp; y_{i} \gt 0 \Rightarrow \bold A_{i} \bold x = b_{i} &amp;&amp;&amp; \forall i \\
\end{aligned}
$$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;${\bold x}^{\star}$ と ${\bold y}^{\star}$ が主問題と双対問題の最適解であるとき以下が成立します．&lt;/p&gt;
$$
\begin{aligned}
&amp;&amp; \bold c^{T} \bold x^{\star} = \bold b^{T} \bold y^{\star} \\
\end{aligned}
$$&lt;h2 id="primal-dual-algorithm"&gt;Primal Dual Algorithm
&lt;/h2&gt;&lt;p&gt;primal dual algorithm は線形計画問題を解くための一般的なアルゴリズムです．&lt;br&gt;
primal dual algorithm を用いて主問題の最適解 ${\bold x}^{\star}$ を求めます．簡単のため，主問題には実行可能解があると仮定します．primal dual algorithm は以下のように実行されます．双対問題の実行可能性が常に維持されていることに注意してください．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;双対問題の実行可能解 $\bold y$ を求める&lt;/li&gt;
&lt;li&gt;$\bold y$ をもとに構築した restricted primal problem を解く&lt;/li&gt;
&lt;li&gt;restricted primal problem の最適解の値が $0$ ならば，最適解 $\bold {x}^{\star}$ が判明したということなのでアルゴリズムを終了する&lt;/li&gt;
&lt;li&gt;restricted primal problem の最適解の値が $0$ でないならば，restricted primal problem の双対問題である dual restricted primal の最適解を求める．この解を $\bold z$ とする&lt;/li&gt;
&lt;li&gt;ある $\epsilon$ を求め，${\bold y}^{\prime} = {\bold y} + \epsilon {\bold z}$ を新たな双対問題の実行可能解として採用し，2 に戻る&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;順に詳しくみていきます．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;双対問題の実行可能解 $\bold y$ を適当に求めます．$\bold c \ge 0$ を仮定しているため $\bold y = \bold 0$ とおくことができます．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ある双対問題の解 $\bold y$ が与えられたときに，「主問題の制約の違反」と「相補性条件の違反」を最小にするような主問題の解 $\bold x$ を見 つける問題を考えます．もしこれらの違反量が 0 の $\bold x$ を見つけることができたら，相補性条件よりこの $\bold x$ と $\bold y$ は最適解だということになります．&lt;br&gt;
$J = \lbrace j \mid \bold A^{j} \bold y = c_{j} \rbrace$ とします．これは正になることのできる主問題の変数の index の集合です．すると，この問題は以下のような線形計画問題となります．これを restricted primal(以下 RP)とよびます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Restricted Primal
$$
\begin{aligned}
&amp;\text{minimize} &amp;&amp; \sum_i s_i \\\
&amp;\text{subject to}
&amp;&amp; \sum_{j \in J} \bold A_{ij} \bold x_j + \bold s_i = \bold b_i &amp;&amp;&amp; \forall i\\\
&amp; &amp;&amp; \bold x \geq \bold 0 &amp;&amp;&amp; j \in J\\\
&amp; &amp;&amp; \bold x = \bold 0 &amp;&amp;&amp; j \notin J\\\
&amp; &amp;&amp; \bold s \geq \bold 0
\end{aligned}
$$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;もし RP の最適解の値が $0$ なら，この $(\bold x, \bold y)$ が主問題と双対問題の最適解ということになりアルゴリズムは終了します．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;そうでない場合は相補性条件を満たすような実行可能解 $\bold x$ が見つからなかったということなので，$\bold y$ は双対問題の最適解ではなかったということがわかります．&lt;br&gt;
そこで，$\bold y$ よりも良い双対問題の解を探すことにします．&lt;br&gt;
そのために RP の双対問題である Dual Restricted Primal(以下 DRP)を考えます．これは以下のようになります．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dual Restricted Primal
$$
\begin{aligned}
&amp;\text{maxmize} &amp;&amp; \bold b^{T} \bold z \\\
&amp;\text{subject to}
&amp;&amp; \bold A^{j} \bold z \leq 0 &amp;&amp;&amp; j \in J \\\
&amp; &amp;&amp; z_{i} \leq 1 &amp;&amp;&amp; \forall i \\\
\end{aligned}
$$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DRP の最適解を $\bold z^{\star}$ とします．
双対問題の実行可能解 $\bold y$ に $\bold z^{\star}$ を $\epsilon(\epsilon \gt 0)$ 倍して足し合わせた解 ${\bold y}^{\prime} = \bold y + \epsilon \bold z^{\star}$ を考えます．
実はうまく $\epsilon$ を選ぶことで $\bold y^{\prime}$ は元の解 $\bold y$ よりも良い目的関数値をとり，さらに実行可能解となっています．&lt;br&gt;
$\bold y$ よりも良い解 $\bold y^{\prime}$ が手に入れば，これを新たな双対問題の解として採用し，また 2 に戻り RP を考え&amp;hellip;と手順を繰り返していくことで，やがて最適解を得ることができます．&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最後に，$\bold y^{\prime} = \bold y + \epsilon \bold z^{\star}$ が解 $\bold y$ よりも良い解となることと $\bold y^{\prime}$ が実行可能解となるような $\epsilon$ の選び方を示します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\bold y^{\prime} = \bold y + \epsilon \bold z^{\star}$ が解 $\bold y$ よりも良くなることを示します．&lt;br&gt;
$\bold y^{\prime} = \bold y + \epsilon \bold z$ を双対問題の目的関数に当てはめると $\bold b^{T} \bold y^{\prime} = \bold b^{T} \bold y + \epsilon \bold b^{T} \bold z^{\star}$ となります．&lt;br&gt;
$\epsilon \bold b^{T} \bold z^{\star} \gt 0$ となることを確認します．&lt;br&gt;
$\epsilon$ は $0$ より大きい値をとるため，$\epsilon \gt 0$ となります．&lt;br&gt;
RP の最適解の値は 0 より大きかったため，その双対問題である DRP の最適解の値も 0 より大きいことになります．よって，$\bold b^{T} \bold z^{\star} \gt 0$ といえます．&lt;br&gt;
以上のことから，$\bold y^{\prime}$ が $\bold y$ より良い目的関数値をとることがわかりました．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\bold y^{\prime} = \bold y + \epsilon \bold z^{\star}$ が双対問題の実行可能解となるような $\epsilon$ の選び方を示します．&lt;br&gt;
双対問題の実行可能解になるように制約条件 $\bold A^{T} \bold y^{\prime} \leq \bold c$ を満たすような $\epsilon$ を求めます．&lt;br&gt;
まず，双対問題の制約条件より $\bold A^{T} \bold y \le \bold c$ です．&lt;br&gt;
次に，DRP の制約条件より $j \in J$ については $\bold A^{j} \bold z^{\star} \le 0$ となります．
よって，$j \in J$ であるような $j$ については制約条件を満たすため，$j \notin J$ のうち $\bold A^{j} \bold z^{\star} \gt 0$ である $j$ についてのみ考えます．&lt;br&gt;
このような $j$ は $\epsilon \le \min_{j \notin J: A^{j} \bold z^{\star} \gt 0} \frac{c_j - \bold A^{j} \bold y}{\bold A^{j} \bold z^{\star}}$ を満たす必要があります．&lt;br&gt;
$\epsilon$ は大きい方がいいので，この条件を満たす最大の値を $\epsilon$ として選びます．&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ハンガリアン法"&gt;ハンガリアン法
&lt;/h2&gt;&lt;p&gt;Primal Dual Algorighm を使ってハンガリアン法を導出します．
頂点 $a$ と頂点 $b$ を結ぶ辺を $(a, b) \in E$ とし，その容量を $c_{ab}$ とします．簡単のため $\bold c \ge \bold 0$ とし完全マッチングが存在するものとします．&lt;/p&gt;
&lt;p&gt;以下では，有向グラフを接続行列 $\bold A$ で表します．また，ノードの数を $n$，辺の数を $m$ とします．
二部グラフの最小重み完全マッチングを線形緩和した主問題と双対問題を定義します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主問題&lt;/li&gt;
&lt;/ul&gt;
$$
\begin{aligned}
&amp;\text{minimize} &amp;&amp; \sum_{(a, b) \in E} c_{ab} x_{ab} \\
&amp;\text{subject to}
&amp;&amp; \sum_{b:(a, b) \in E} x_{ab} = 1 &amp;&amp;&amp; a \in A \\
&amp; &amp;&amp; \sum_{a:(a, b) \in E} x_{ab} = 1 &amp;&amp;&amp; b \in B \\
&amp; &amp;&amp; x_{ab} \ge 0 &amp;&amp;&amp; (a, b) \in E\\
\end{aligned}
$$&lt;ul&gt;
&lt;li&gt;双対問題&lt;/li&gt;
&lt;/ul&gt;
$$
\begin{aligned}
&amp;\text{maxiimize} &amp;&amp; \sum_{a \in A} u_{a} + \sum_{b \in B} v_{b} \\
&amp;\text{subject to}
&amp;&amp; u_{a} + v_{b} \le c_{ab} &amp;&amp;&amp; (a, b) in E\\
\end{aligned}
$$&lt;h3 id="ハンガリアン法の導出"&gt;ハンガリアン法の導出
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;双対問題の適当な実行可能解を求めます．$C \ge 0$ を仮定しているため，$\bold u = \bold v = \bold 0$ とすることができます．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;restricted primal を考えます．$J = \lbrace(a, b) \in E : u_{a} + v_{b} = c_{ab} \rbrace$ とすると以下のようになります．これは $J$ の辺のみを使って完全マッチングを求める問題です．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Restricted Primal
$$
\begin{aligned}
&amp;\text{minimize} &amp;&amp; \sum_{a \in A} s_{a} + \sum_{b \in B} s_{b} \\\
&amp;\text{subject to}
&amp;&amp; \sum_{b:(a, b) \in E} x_{ab} + s_{a} = 1 &amp;&amp;&amp; a \in A\\\
&amp; &amp;&amp; \sum_{a:(a, b) \in E} x_{ab} + s_{b} = 1 &amp;&amp;&amp; b \in B\\\
&amp; &amp;&amp; x_{ab} &gt;= 0 &amp;&amp;&amp; (a, b) \in J \\\
&amp; &amp;&amp; x_{ab} = 0　&amp;&amp;&amp; (a, b) \in (E - J) \\\
&amp; &amp;&amp; s \ge 0
\end{aligned}
$$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$J$ の辺のみをつかって完全マッチングを作ることができれば，RP の目的関数値を 0 にすることができます．
辺の重みを考えなくてよくなったため，2 部グラフの最大マッチングを求めるアルゴリズムを使うことができます．
もし完全マッチングがみつかればアルゴリズムは終了します．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;見つからない場合は dual restricted primal を考えます．DRP は $J$ の辺のみを使ったグラフ上で最小点被覆を求める問題です．これは RP で求めた最大マッチングの解を使って求めることができます ．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dual Restricted Primal
$$
\begin{aligned}
&amp;\text{maximize} &amp;&amp; \sum_{a \in A} u^{\prime}_{a} + \sum_{b \in B} v^{\prime}_{b} \\\
&amp;\text{subject to}
&amp;&amp; u^{\prime}_{a} + v^{\prime}_{b} \le 0 &amp;&amp;&amp; (a, b) \in J \\\
&amp; &amp;&amp; u^{\prime}_{a} \le 1 &amp;&amp;&amp; a \in A\\\
&amp; &amp;&amp; v^{\prime}_{b} \le 1 &amp;&amp;&amp; b \in B
\end{aligned}
$$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DRP の解を求め，$u^{\prime \prime} = u + \epsilon u^{\prime}$，$v^{\prime \prime} = v + \epsilon v^{\prime}$とします．ここで $\epsilon = \min_{(a, b) \in (E - J)}(c_{ab} - u_{a} - v_{b})$ とすることができます．あとは，$u^{\prime}$ と $v^{\prime}$ を新しい双対問題の解として採用し，2 に戻ります．&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="参考文系"&gt;参考文系
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.amazon.co.jp/dp/B00C8UQZAO/" target="_blank" rel="noopener"
&gt;Combinatorial Optimization: Algorithms and Complexity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ocw.mit.edu/courses/18-433-combinatorial-optimization-fall-2003/92c255b407a6ad7d75c9ea55de2fdf33_l15.pdf" target="_blank" rel="noopener"
&gt;18.433 Combinatorial Optimization The Primal-dual Algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://math.mit.edu/~goemans/PAPERS/book-ch4.pdf" target="_blank" rel="noopener"
&gt;CHAPTER 4 THE PRIMAL-DUAL METHOD FOR APPROXIMATION ALGORITHMS AND ITS APPLICATION TO NETWORK DESIGN PROBLEMS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ICLを受けてきた</title><link>https://miti-7.github.io/post/icl%E3%82%92%E5%8F%97%E3%81%91%E3%81%A6%E3%81%8D%E3%81%9F/</link><pubDate>Mon, 24 Feb 2025 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/icl%E3%82%92%E5%8F%97%E3%81%91%E3%81%A6%E3%81%8D%E3%81%9F/</guid><description>&lt;h2 id="icl"&gt;ICL
&lt;/h2&gt;&lt;p&gt;ICL 手術を &lt;a class="link" href="https://eyeclinic-tokyo.jp/" target="_blank" rel="noopener"
&gt;アイクリニック東京&lt;/a&gt; で受けてきました．&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;日&lt;/th&gt;
&lt;th&gt;event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;-43&lt;/td&gt;
&lt;td&gt;診察の予約をする&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-31&lt;/td&gt;
&lt;td&gt;初診適応検査をする&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-25&lt;/td&gt;
&lt;td&gt;レンズ度数決定のための検査をする&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-21&lt;/td&gt;
&lt;td&gt;レンズの準備完了の電話がくる．手術日，翌日検査，１週間後検査の予約をする&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-3 ～ -1&lt;/td&gt;
&lt;td&gt;抗菌薬&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;を 1 日 4 回点眼する&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;手術日．手術前の抗菌薬点眼は朝と昼の 2 回行う．&lt;br&gt;手術後に 3 種類の目薬&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;の点眼を開始&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;手術翌日検査をする．首から下のシャワーのみ可能&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 ～ 6&lt;/td&gt;
&lt;td&gt;目薬&lt;sup id="fnref1:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;を 1 日 4 回点眼する．保護メガネ着用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;手術 1 週間後検査をする&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8 ～ 34&lt;/td&gt;
&lt;td&gt;目薬&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;を 1 日 4 回点眼する．以降保護メガネは外していい&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;手術 1 ヶ月後検査をする&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;36 ～&lt;/td&gt;
&lt;td&gt;目薬&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;を 1 日 3 回点眼する．&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;93&lt;/td&gt;
&lt;td&gt;手術 3 ヶ月後検査をする&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="初診適応検査"&gt;初診適応検査
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ICL を受けられるかの検査や視力の検査を行う
&lt;ul&gt;
&lt;li&gt;最初の問診票で執刀医の希望を書く欄があるので院長を指定した&lt;/li&gt;
&lt;li&gt;検査結果は問題なかった&lt;/li&gt;
&lt;li&gt;視力，屈折度，角膜曲率半径，眼圧検査の結果が貰える&lt;/li&gt;
&lt;li&gt;全体で 80 分くらいかかった&lt;/li&gt;
&lt;li&gt;レンズ度数のシミュレーションをする．度数の強さと乱視補正をどうするかを次回までに決める
&lt;ul&gt;
&lt;li&gt;乱視付き ICL(トーリック ICL)にすると +5 万かかり，将来的に軸がずれ再手術しなければならない可能性がある&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;検査代として 1 万円支払うが，ICL を受ければ返ってくる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="レンズ度数決定のための検査"&gt;レンズ度数決定のための検査
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;視力は前回の検査と変わらなかった
&lt;ul&gt;
&lt;li&gt;詳細なデータは貰えなかった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;レンズ度数の本決定
&lt;ul&gt;
&lt;li&gt;度数
&lt;ul&gt;
&lt;li&gt;PC を使う時間が多いので 2 段階強さを落としてもらった
&lt;ul&gt;
&lt;li&gt;具体的な強さを指定するのではなく，MAX から何段階落とすかを指定する形式だった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;乱視補正
&lt;ul&gt;
&lt;li&gt;眼鏡では乱視補正をしているのと，軸がずれる可能性は低いということで乱視用のレンズにした&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;前金 30 万を払う&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="手術"&gt;手術
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;病院
&lt;ul&gt;
&lt;li&gt;病院に到着後まず残金を支払い，その後の手術の説明をうける
&lt;ul&gt;
&lt;li&gt;瞳孔を開く目薬をさすので必要な手続きはすべて最初に行う&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;5 分ごとに目薬をする．スタッフが時間を教えてくれるわけではないので自分で時間を測る必要がある&lt;/li&gt;
&lt;li&gt;時々スタッフが来て目の状態を確認する．結局 11 回ほど目薬をしたあとに手術室に呼ばれる&lt;/li&gt;
&lt;li&gt;手術の最中は執刀医がどんな状況か教えてくれる
&lt;ul&gt;
&lt;li&gt;全部あわせて 5 分くらいで終わった&lt;/li&gt;
&lt;li&gt;痛みはないが目に強い圧迫感があり精神的に厳しかった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;全部で 2 時間くらいで終了した&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;帰宅後
&lt;ul&gt;
&lt;li&gt;目薬を 1 時間ごとにさす&lt;/li&gt;
&lt;li&gt;ハローとグレアがかなりすごい．マウスのカーソルにもハローが見える&lt;/li&gt;
&lt;li&gt;目がゴロゴロする&lt;/li&gt;
&lt;li&gt;ひたすら目をつぶってはやめに寝た&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="翌日検査"&gt;翌日検査
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;体調
&lt;ul&gt;
&lt;li&gt;ハローとグレアはほぼないが真っ暗な部屋で白いモニターをみるとハローが少しみえる&lt;/li&gt;
&lt;li&gt;目薬をさすときに目の周辺に黒い影がみえる．メガネの縁が見えているような感じ
&lt;ul&gt;
&lt;li&gt;病院で質問したらレンズの影とのこと
&lt;ul&gt;
&lt;li&gt;そのうち脳内補正されて気にならなくなるらしい&lt;/li&gt;
&lt;li&gt;目薬のときくらいしか見えないので日常生活に問題はなさそう&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;病院
&lt;ul&gt;
&lt;li&gt;眼圧検査，視力検査，検診をした&lt;/li&gt;
&lt;li&gt;両目とも 1.5 になっていた
&lt;ul&gt;
&lt;li&gt;予定より視力があがってしまっていた&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="1-週間後検査"&gt;1 週間後検査
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;眼圧検査，視力検査，検診をした
&lt;ul&gt;
&lt;li&gt;特に問題なし&lt;/li&gt;
&lt;li&gt;両目とも 1.5 のまま&lt;/li&gt;
&lt;li&gt;リンデロン点眼からフルメトロン点眼液 0.1% に変更&lt;/li&gt;
&lt;li&gt;ドライアイがあるのでドライアイ用の目薬&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;を出してもらう&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="1-ヶ月後検査"&gt;1 ヶ月後検査
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;眼圧検査，レンズのズレの検査，角膜内皮細胞数検査，視力検査，検診をした
&lt;ul&gt;
&lt;li&gt;特に問題なし&lt;/li&gt;
&lt;li&gt;両目とも 1.5 のまま&lt;/li&gt;
&lt;li&gt;フルメトロン点眼液は使い切ったら終了で，クラビット点眼液とジクロフェナク Na 点眼液を 1 本ずつ処方された．これらを使い切ったら終了&lt;/li&gt;
&lt;li&gt;問題がなく順調ですねと言われて一瞬で終わってしまった．細胞数がどうなっているのかとか聞いたら教えてもらえるのだろうか？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="3-ヶ月後検査"&gt;3 ヶ月後検査
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;眼圧検査，レンズのズレの検査，角膜内皮細胞数検査，視力検査，検診をした
&lt;ul&gt;
&lt;li&gt;特に問題なし&lt;/li&gt;
&lt;li&gt;両目とも 1.5 のまま&lt;/li&gt;
&lt;li&gt;レンズのズレもなく，傷口も完治しているとのことだった&lt;/li&gt;
&lt;li&gt;必ず実施しないといけない検査は今回で終わり
&lt;ul&gt;
&lt;li&gt;6 ヶ月後検査や 1 年後検査はオプションらしい&lt;/li&gt;
&lt;li&gt;3 年までの検査は無料&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="料金"&gt;料金
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;73 万円 + 5 万円 - 2 万円 = 76 万円
&lt;ul&gt;
&lt;li&gt;基本料金：73 万円&lt;/li&gt;
&lt;li&gt;乱視あり(片側のみ)：5 万円&lt;/li&gt;
&lt;li&gt;平日割：-2 万円&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;料金がはっきりしているのはかなりよかった
&lt;ul&gt;
&lt;li&gt;オプションを勧められるみたいな手間が一切なかった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="懸念したこと"&gt;懸念したこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;レンズの回転（軸ずれ）
&lt;ul&gt;
&lt;li&gt;トーリックレンズの場合はレンズの軸がずれると見え方が悪化してしまう（通常のレンズだと回転しても問題はない）
&lt;ul&gt;
&lt;li&gt;病院で軸がずれたときの見え方をシミュレーションしたがかなりきつい感じだった&lt;/li&gt;
&lt;li&gt;軸ずれが起きる確率は 0.1 % くらいとのことなのでなにもないことに賭けた&lt;/li&gt;
&lt;li&gt;3 年保証がありもし回転しても補正は無料なのと，どうしてもずれてしまうなら通常のレンズを入れ直そうと思っている
&lt;ul&gt;
&lt;li&gt;今のところ問題はない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="気になったこと"&gt;気になったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;レンズ度数を決めたとき，どのレンズになるのかの書類が貰えず口約束になってしまっていた．今回は問題なかったけどトラブル防止に書類を貰っておけばよかった．
&lt;ul&gt;
&lt;li&gt;そもそも書類を貰えるのか不明だが&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;手術前は丁寧なのだけど，手術後の検査はとにかくはやく終わらせよう感がすごい
&lt;ul&gt;
&lt;li&gt;Google のレビューにも結構書いてある&lt;/li&gt;
&lt;li&gt;全員がこういう態度なわけではなく，雑な人と丁寧な人がいる感じだった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;ベガモックス点眼液 0.5%&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;クラビット点眼液 1.5%，リンデロン点眼・点耳・点鼻液 0.1％，ジクロフェナク Na 点眼液 0.1%&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;クラビット点眼液 1.5%，フルメトロン点眼液 0.1%，ジクロフェナク Na 点眼液 0.1%&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;クラビット点眼液 1.5%，ジクロフェナク Na 点眼液 0.1%&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;ヒアルロン酸ナトリウム点眼液 0.1％&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Quadratic Pseudo-Boolean Optimization</title><link>https://miti-7.github.io/post/quadratic-pseudo-boolean-optimization/</link><pubDate>Thu, 09 Jan 2025 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/quadratic-pseudo-boolean-optimization/</guid><description>&lt;img src="https://miti-7.github.io/post/quadratic-pseudo-boolean-optimization/images/general_sample_ab_1.png" alt="Featured image of post Quadratic Pseudo-Boolean Optimization" /&gt;&lt;h2 id="quadratic-pseudo-boolean-optimization"&gt;Quadratic Pseudo-Boolean Optimization
&lt;/h2&gt;&lt;p&gt;次の関数 $E(\bold x)$ を最小化する問題を考えます．$x_{p} \in \lbrace 0, 1 \rbrace$ とし，$\theta_{const}$ は定数を表します．この問題を &lt;a class="link" href="https://en.wikipedia.org/wiki/Quadratic_pseudo-Boolean_optimization" target="_blank" rel="noopener"
&gt;Quadratic Pseudo-Boolean Optimization&lt;/a&gt;(以下 QPBO)と呼びます．&lt;/p&gt;
$$
\begin{equation}
E(\bold x) = \theta_{const} + \sum_p \theta_{p}(x_p) + \sum_{p \lt q} \theta_{pq}(x_p, x_q)
\end{equation}
$$&lt;p&gt;競プロ界隈で「燃やす埋める」や「Project Selection Problem」などと言われる問題は QPBO に帰着することができます&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;．&lt;br&gt;
これらの問題は minimum s-t cut に帰着して解くことができますが，どのように辺を張るかなど混乱しがちです．本記事の目的は QPBO を解くアルゴリズムをライブラリ化することで，問題を解くときに辺の張り方や変数のフリップ操作などを考えなくてすむようにすることです．実装は &lt;a class="link" href="https://github.com/MitI-7/CompetitiveProgrammingLibrary/blob/1c8b83e0e54a6729cce7cf2c7eee09d1de0e4c05/library/cpp/optimization/QPBO.hpp" target="_blank" rel="noopener"
&gt;QPBO.hpp&lt;/a&gt; にあります．&lt;/p&gt;
&lt;p&gt;記事の構成は以下の通りです．&lt;br&gt;
&lt;a class="link" href="#1-s-t-cut" &gt;節 1&lt;/a&gt; では s-t cut と minimum s-t cut の説明をします．minimum s-t cut は多項式時間で求めることができます．&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="#2-%e5%8d%98%e7%b4%94%e3%81%aa%e9%96%a2%e6%95%b0%e3%81%ae%e5%a0%b4%e5%90%88" &gt;節 2&lt;/a&gt; では関数 $E(\bold x)$ が $\theta_{pq}(0, 0) = \theta_{pq}(1, 1) = 0$ であり，どの関数も $0$ 以上の値を返すという単純な関数の場合について考えます．
この場合は minimum s-t cut を見つける問題にそのまま帰着できます．&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="#3-%e5%8a%a3%e3%83%a2%e3%82%b8%e3%83%a5%e3%83%a9%e9%96%a2%e6%95%b0%e3%81%ae%e5%a0%b4%e5%90%88" &gt;節 3&lt;/a&gt; では節 2 の仮定を排除し，関数 $E(\bold x)$ が劣モジュラ関数であるという仮定のみをおいた場合について考えます．&lt;br&gt;
この場合は再パラメータ化という操作を行うことで単純な関数の場合に帰着させることができます．&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="#4-%e4%b8%80%e8%88%ac%e3%81%ae%e9%96%a2%e6%95%b0%e3%81%ae%e5%a0%b4%e5%90%88" &gt;節 4&lt;/a&gt; では関数 $E(\bold x)$ が一般の関数の場合について考えます．&lt;br&gt;
$E(\bold x)$ が一般の関数の場合，これを最小化する問題は NP-hard であり，多項式時間で解くことは(今のところ)できそうもありません．この場合は問題を緩和することで劣モジュラ関数の場合に帰着させ近似解を得ることができます．さらに，ここで得られた解は最適解の一部となることが保証されます．&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="#5-%e5%95%8f%e9%a1%8c" &gt;節 5&lt;/a&gt; では競プロの問題をいくつか解いていきます．&lt;/p&gt;
&lt;h2 id="1-s-t-cut"&gt;1. s-t cut
&lt;/h2&gt;&lt;p&gt;頂点集合 $V$ と 有向辺 $E$ からなる有向グラフ $G = (V, E)$ が与えられます．辺 $(i, j)$ には容量 $c_{ij} \ge 0$ が定まっているものとします．&lt;br&gt;
頂点集合 $V$ を 2 つの部分集合 $S$ と $T = V \backslash S$ に分割します．2 つのノード $s$ と $t$ について $s \in S$，$t \in T$ となるような分割を s-t cut と呼びます．&lt;br&gt;
$S$ から出て $T$ に入るような辺の容量の総和を s-t cut の容量と呼び，以下で定義されます．すべての s-t cut のうち最小のものを minimum s-t cut と呼びます．&lt;/p&gt;
$$
\begin{aligned}
c(S) = \sum_{(i, j) \in (S, T)} c_{ij}
\end{aligned}
$$&lt;p&gt;下のグラフの s-t cut の例をいくつか見ていきます &lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;．&lt;/p&gt;
&lt;img src="images/s-t-cut_sample1.png" width="50%"&gt;
&lt;p&gt;頂点の部分集合として，$S = \lbrace s, 0, 1 \rbrace$ を選んだとします．&lt;br&gt;
$S$ に属する頂点を赤，$T = V \backslash S$ に属する頂点を青で示します． $S$ から出て $T$ に入るような辺は辺 (0, 2) と辺 (1, 3) です．よって，この s-t cut の容量は 3 + 2 = 5 となります．&lt;br&gt;
すべての s-t cut の中でこのカットより容量の小さい s-t cut は存在しないのでこれは minimum s-t cut です．&lt;/p&gt;
&lt;img src="images/s-t-cut_sample2.png" width="50%"&gt;
&lt;p&gt;頂点の部分集合として $S = \lbrace s, 0, 1, 2, 3 \rbrace$ を選んだとします．&lt;br&gt;
この s-t cut の容量は 2 + 3 = 5 となります．&lt;br&gt;
このカットも minimum s-t cut です．このように minimum s-t cut は複数存在することがあります．&lt;/p&gt;
&lt;img src="images/s-t-cut_sample3.png" width="50%"&gt;
&lt;p&gt;頂点の部分集合として $S = \lbrace s, 1, 2 \rbrace$ を選んだとします．&lt;br&gt;
この s-t cut の容量は，3 + 2 + 4 + 2 = 11 となります．&lt;br&gt;
辺 (0, 1) や辺 (0, 2) は $T$ から $S$ に入る辺なので含まれません．&lt;/p&gt;
&lt;img src="images/s-t-cut_sample4.png" width="50%"&gt;
&lt;p&gt;minimum s-t cut は最大流問題を解き，残余ネットワーク上で頂点 $s$ から到達できる頂点集合を $S$ とすることで求められます．詳しくは &lt;a class="link" href="https://ja.wikipedia.org/wiki/%E6%9C%80%E5%A4%A7%E3%83%95%E3%83%AD%E3%83%BC%E6%9C%80%E5%B0%8F%E3%82%AB%E3%83%83%E3%83%88%E5%AE%9A%E7%90%86" target="_blank" rel="noopener"
&gt;最大フロー最小カット定理&lt;/a&gt; などを参照してください．&lt;br&gt;
次節から s-t cut を使って $E(\bold x)$ を最小化する方法を見ていきます．&lt;/p&gt;
&lt;h2 id="2-単純な関数の場合"&gt;2. 単純な関数の場合
&lt;/h2&gt;&lt;p&gt;関数 $E(\bold x)$ を最小化する方法を考えていきます．$x_{p} \in \lbrace 0, 1 \rbrace$ なので，変数の個数が $n$ 個のとき解は $2^n$ 個存在します．この $2^n$ 個の解のなかから最小のものを見つけるのが目標です．&lt;/p&gt;
$$
\begin{equation}
E(\bold x) = \theta_{const} + \sum_{p} \theta_{p}(x_p) + \sum_{p \lt q} \theta_{pq}(x_p, x_q) \tag {1}
\end{equation}
$$&lt;p&gt;単純な関数の場合を考えたいので，$\theta_{pq}(0, 0) = \theta_{pq}(1, 1) = 0$ であり，すべて 0 以上の値を返すと仮定します．&lt;br&gt;
この仮定を満たす関数の場合は $E(\bold x)$ の解と s-t cut の解が 1 対 1 対応するようなグラフを作成することができます．よって，グラフの最小 s-t cut がわかれば $E(\bold x)$ の最小値（= 最適解）を求めることができます．&lt;/p&gt;
&lt;p&gt;グラフは各変数を頂点とし，これに特別な頂点 $s$ と $t$ を加えた $n + 2$ 個の頂点から構成されます．辺は下記のルールにしたがって張ります．&lt;/p&gt;
&lt;div style="display: flex; gap: 20px;"&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;関数&lt;/th&gt;
&lt;th&gt;辺&lt;/th&gt;
&lt;th&gt;容量&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{p}(0)$&lt;/td&gt;
&lt;td&gt;$p \rightarrow t$&lt;/td&gt;
&lt;td&gt;$\theta_{p}(0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{p}(1)$&lt;/td&gt;
&lt;td&gt;$s \rightarrow p$&lt;/td&gt;
&lt;td&gt;$\theta_{p}(1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq}(0, 1)$&lt;/td&gt;
&lt;td&gt;$p \rightarrow q$&lt;/td&gt;
&lt;td&gt;$\theta_{pq}(0, 1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq}(1, 0)$&lt;/td&gt;
&lt;td&gt;$q \rightarrow p$&lt;/td&gt;
&lt;td&gt;$\theta_{pq}(1, 0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;具体例として，変数が $a$ と $b$ の 2 つだけの場合を見てみます．&lt;br&gt;
各変数の値に対応する $E(\bold x) = \theta_a(a) + \theta_b(b) + \theta_{ab}(a, b)$ の値は以下のようになります．$\theta_{ab}(0, 0)$ と $\theta_{ab}(1, 1)$ の値は $0$ であり，$\theta_{const}$ は定数のため省略しています．&lt;/p&gt;
&lt;div style="display: flex; gap: 20px;"&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;a&lt;/th&gt;
&lt;th&gt;b&lt;/th&gt;
&lt;th&gt;$E(\bold x)$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{a}(0) + \theta_{b}(0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{a}(0) + \theta_{b}(1) + \theta_{ab}(0, 1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{a}(1) + \theta_{b}(0) + \theta_{ab}(1, 0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{a}(1) + \theta_{b}(1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ルールに従うと下のグラフが構築されます．&lt;br&gt;
このグラフの s-t cut をいくつか見ていきます．&lt;/p&gt;
&lt;img src="images/simple_sample.png" width="25%"&gt;
&lt;p&gt;$S = \lbrace s, a, b \rbrace$ とします．この s-t cut の容量は $\theta_{a}(0) + \theta_{b}(0)$ です．&lt;br&gt;
また，$a = 0$，$b = 0$ としたとき $E(\bold x)$ の値は $\theta_{a}(0) + \theta_{b}(0)$ です．&lt;br&gt;
よって，$S = \lbrace s, a, b \rbrace$ としたときの s-t cut の容量と，$a = 0$，$b = 0$ としたときの $E(\bold x)$ の関数値は一致しています．&lt;/p&gt;
&lt;img src="images/simple_cut1.png" width="25%"&gt;
&lt;p&gt;別の s-t cut の例をみます．&lt;br&gt;
$S = \lbrace s, a \rbrace$ とします．この s-t cut の容量は $\theta_{a}(0) + \theta_{b}(1) + \theta_{ab}(0, 1)$ です．&lt;br&gt;
また，$a = 0$，$b = 1$ としたとき $E(\bold x)$ の値は $\theta_{a}(0) + \theta_{b}(1) + \theta_{ab}(0, 1)$ です．&lt;br&gt;
よって，$S = \lbrace s, a \rbrace$ としたときの s-t cut の容量と，$a = 0$，$b = 1$ としたときの $E(\bold x)$ の関数値は一致しています．&lt;/p&gt;
&lt;img src="images/simple_cut2.png" width="25%"&gt;
&lt;p&gt;変数が 2 つの場合は s-t cut は $2^2$ 通りあります．すべてのパターンは以下の通りです．&lt;/p&gt;
&lt;img src="images/simple_cut_all.png" width="50%"&gt;
&lt;p&gt;このように s-t cut の構成と $E(\bold x) $ の構成が 1 対 1 対応するため，minimum s-t cut を計算することで $E(\bold x)$ の最小値を求めることができます．&lt;br&gt;
minimum s-t cut を計算し，$S$ に属する頂点に対応する変数の値を $0$，$T$ に属する頂点に対応する変数の値を $1$ と設定することで最適な $\bold x$ を構成できます．&lt;/p&gt;
&lt;h2 id="3-劣モジュラ関数の場合"&gt;3. 劣モジュラ関数の場合
&lt;/h2&gt;&lt;p&gt;「&lt;a class="link" href="#2-%e5%8d%98%e7%b4%94%e3%81%aa%e9%96%a2%e6%95%b0%e3%81%ae%e5%a0%b4%e5%90%88" &gt;2. 単純な関数の場合&lt;/a&gt;」では，$\theta_{pq}(0, 0) = \theta_{pq}(1, 1) = 0$ とし，どの関数も $0$ 以上の値を返すことを仮定していました．&lt;br&gt;
この節ではこの仮定を排除し，関数は劣モジュラであることのみを仮定します．今回は 2 値変数を考えているので，$\theta_{pq}(0, 1) + \theta_{pq}(1, 0) \ge \theta_{pq}(0, 0) + \theta_{pq}(1, 1)$ を満たすことになります．&lt;/p&gt;
&lt;p&gt;$\theta_{pq}(0, 0)$ や $\theta_{pq}(1, 1)$ が $0$ 以外の値をとったり関数値が負の値をとる場合があるので，今回はルール通りにグラフを作ることはできません．そこで再パラメータ化という操作を行います．再パラメータ化とは，$E(\bold x)$ の関数値を保ちつつ $\theta_{pq}(1, 0)$ などの各関数値を変化させる操作です．&lt;br&gt;
再パラメータ化を行うと標準形とよばれる以下の条件を満たす形になります&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;．標準形ではどの関数も $0$ 以上の値をとります．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$min \lbrace \theta_{p}(0), \theta_{p}(1) \rbrace = 0$&lt;/li&gt;
&lt;li&gt;$min \lbrace \theta_{pq}(0, 0), \theta_{pq}(1, 0) \rbrace = 0$&lt;/li&gt;
&lt;li&gt;$min \lbrace \theta_{pq}(0, 1), \theta_{pq}(1, 1) \rbrace = 0$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再パラメータ化をすると，関数 $\theta_{pq}(x_{p}, x_{q})$ が劣モジュラの場合は $\theta_{pq}(0, 0) = \theta_{pq}(1, 1) = 0$ に，関数 $\theta_{pq}(x_{p}, x_{q})$ が優モジュラの場合は $\theta_{pq}(0, 1) = \theta_{pq}(1, 0) = 0$ になります&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;．&lt;br&gt;
よって，すべての $\theta_{pq}(x_{p}, x_{q})$ が劣モジュラ関数の場合は，再パラメータ化をすることで「&lt;a class="link" href="#2-%e5%8d%98%e7%b4%94%e3%81%aa%e9%96%a2%e6%95%b0%e3%81%ae%e5%a0%b4%e5%90%88" &gt;2. 単純な関数の場合&lt;/a&gt;」に帰着することができます．&lt;br&gt;
再パラメータ化の手続きは以下の通りです．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;step1
&lt;ul&gt;
&lt;li&gt;すべての (p, q) の各 $j \in \lbrace 0, 1 \rbrace$ について
&lt;ul&gt;
&lt;li&gt;$\delta = min \lbrace \theta_{pq}(0, j), P_{pq}(1, j) \rbrace$&lt;/li&gt;
&lt;li&gt;$\theta_{pq}(0, j) = \theta_{pq}(0, j) - \delta$&lt;/li&gt;
&lt;li&gt;$\theta_{pq}(1, j) = \theta_{pq}(1, j) - \delta$&lt;/li&gt;
&lt;li&gt;$\theta_{q}(j) = \theta_{q}(j) + \delta$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;step2
&lt;ul&gt;
&lt;li&gt;$\delta = min \lbrace \theta_p(0), \theta_p(1) \rbrace$&lt;/li&gt;
&lt;li&gt;$\theta_{p}(0) = \theta_{p}(0) - \delta$&lt;/li&gt;
&lt;li&gt;$\theta_{p}(1) = \theta_{p}(1) - \delta$&lt;/li&gt;
&lt;li&gt;$\theta_{const} = \theta_{const} + \delta$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再パラメータ化をしたとき，目的関数値が変化しないことを確認します．&lt;br&gt;
step 1 の $j = 0$ では，$\theta_{pq}(0, 0)$ と $\theta_{pq}(1, 0)$ から $\delta$ を引き，$\theta_{q}(0)$ に $\delta$ を加えます．&lt;br&gt;
この操作を行うと $E(\bold x)$ は以下の表のように変化します．$\delta$ が打ち消し合って，目的関数値が保たれていることが確認できます．&lt;br&gt;
また，$\delta$ として $min \lbrace \theta_{pq}(0, 0), P_{pq}(1, 0) \rbrace$ を選んでいるので，$min \lbrace \theta_{pq;00}, \theta_{pq;10} \rbrace = 0$ を満たすようになります．&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;p&lt;/th&gt;
&lt;th&gt;q&lt;/th&gt;
&lt;th&gt;$E(\bold x)$&lt;/th&gt;
&lt;th&gt;$E^{\prime}(\bold x)$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + \theta_{q}(0) + \theta_{ab}(0, 0)$&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + (\theta_{q}(0) + \delta) + (\theta_{ab}(0, 0) - \delta)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + \theta_{q}(1) + \theta_{ab}(0, 1)$&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + \theta_{q}(1) + \theta_{ab}(0, 1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + \theta_{q}(0) + \theta_{ab}(1, 0)$&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + (\theta_{q}(0) + \delta) + (\theta_{ab}(1, 0) - \delta)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + \theta_{q}(1) + \theta_{ab}(1, 1)$&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + \theta_{q}(1) + \theta_{ab}(1, 1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;step 1 の $j = 1$ では，$\theta_{pq}(0, 1)$ と $\theta_{pq}(1, 1)$ から $\delta$ を引き，$\theta_{q}(1)$ に $\delta$ を加えます．&lt;br&gt;
$\delta$ として $min \lbrace \theta_{pq}(0, 1), P_{pq}(1, 1) \rbrace$ を選んでいるので，$min \lbrace \theta_{pq;01}, \theta_{pq;11} \rbrace = 0$ を満たすようになります．&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;p&lt;/th&gt;
&lt;th&gt;q&lt;/th&gt;
&lt;th&gt;$E(\bold x)$&lt;/th&gt;
&lt;th&gt;$E^{\prime}(\bold x)$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + \theta_{q}(0) + \theta_{ab}(0, 0)$&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + \theta_{q}(0) + \theta_{ab}(0, 0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + \theta_{q}(1) + \theta_{ab}(0, 1)$&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + (\theta_{q}(1) + \delta) + (\theta_{ab}(0, 1) - \delta)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + \theta_{q}(0) + \theta_{ab}(1, 0)$&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + \theta_{q}(0) + \theta_{ab}(1, 0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + \theta_{q}(1) + \theta_{ab}(1, 1)$&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + (\theta_{q}(1) + \delta) + (\theta_{ab}(1, 1) - \delta)$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;step 2 では，$\theta_{p}(0)$ と $\theta_{p}(1)$ から $\delta$ を引き，$\theta_{const}$ に $\delta$ を加えます．&lt;br&gt;
$\delta$ として $min \lbrace \theta_p(0), \theta_p(1) \rbrace$ を選んでいるので，$min \lbrace \theta_{p;0}, \theta_{p;1} \rbrace = 0$ を満たすようになります．&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;p&lt;/th&gt;
&lt;th&gt;q&lt;/th&gt;
&lt;th&gt;$E(\bold x)$&lt;/th&gt;
&lt;th&gt;$E^{\prime}(\bold x)$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + \theta_{q}(0) + \theta_{ab}(0, 0)$&lt;/td&gt;
&lt;td&gt;$(\theta_{const} + \delta) + (\theta_{p}(0) - \delta) + \theta_{q}(0) + \theta_{ab}(0, 0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(0) + \theta_{q}(1) + \theta_{ab}(0, 1)$&lt;/td&gt;
&lt;td&gt;$(\theta_{const} + \delta) + (\theta_{p}(0) - \delta) + \theta_{q}(1) + \theta_{ab}(0, 1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + \theta_{q}(0) + \theta_{ab}(1, 0)$&lt;/td&gt;
&lt;td&gt;$(\theta_{const} + \delta) + (\theta_{p}(1) - \delta) + \theta_{q}(0) + \theta_{ab}(1, 0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{const} + \theta_{p}(1) + \theta_{q}(1) + \theta_{ab}(1, 1)$&lt;/td&gt;
&lt;td&gt;$(\theta_{const} + \delta) + (\theta_{p}(1) - \delta) + \theta_{q}(1) + \theta_{ab}(1, 1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="4-一般の関数の場合"&gt;4. 一般の関数の場合
&lt;/h1&gt;&lt;p&gt;関数に何も仮定を置かない場合は $E(\bold x)$ の最小化は NP-hard なので，minimum s-t cut 問題に帰着できない場合があります．&lt;br&gt;
この場合でも最適解はだせなくても問題を解けるだけ解く QPBO 法というアルゴリズムがあります&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;．QPBO 法は解として $x_p = \lbrace 0, 1, \emptyset \rbrace$ のいずれかを与えます．$\emptyset$ は解が不明であることを表します．$x_p$ に $0$ か $1$ の値が与えられたとき，$x_p$ はラベル付けされたといいます．&lt;br&gt;
このアルゴリズムは次のような性質があります．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;アルゴリズムの出力を $\bold x$ とする．完全にラベル付けされた任意の解 $\bold y$ があるとき，以下のように $\bold z$ を定めると常に $E(\bold z) \le E(\bold y)$ を満たす．&lt;/li&gt;
&lt;/ol&gt;
$$
z_p = \left\{
\begin{array}{ll}
x_p &amp; \text{if} \space x_p \in \lbrace 0, 1 \rbrace \\
y_p &amp; \text{if} \space x_p = \emptyset
\end{array}
\right.
$$&lt;ol start="2"&gt;
&lt;li&gt;関数のすべての項が劣モジュラのとき最適解が求まる．&lt;/li&gt;
&lt;li&gt;アルゴリズムはフリップ操作に対して不変である．&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;性質 1 で $\bold y$ に最適解を選べば $\bold x$ は常に最適解の一部となることがわかります．&lt;br&gt;
競プロで役に立つのは性質 2 と 3 です．この 2 つの性質から，すべての項を劣モジュラにするようなフリップ操作がある場合に QPBO 法は最適解を求めることがわかります．&lt;/p&gt;
&lt;p&gt;QPBO 法を説明します．&lt;br&gt;
以降は表記が煩雑になるのを避けるためこの節では関数値を以下のように表記することがあります．&lt;/p&gt;
&lt;div style="display: flex; gap: 20px;"&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{p}(0)$&lt;/td&gt;
&lt;td&gt;$\theta_{p;0}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{p}(1)$&lt;/td&gt;
&lt;td&gt;$\theta_{p;1}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq}(0,0)$&lt;/td&gt;
&lt;td&gt;$\theta_{pq;00}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq}(0,1)$&lt;/td&gt;
&lt;td&gt;$\theta_{pq;01}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq}(1,0)$&lt;/td&gt;
&lt;td&gt;$\theta_{pq;10}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq}(1,1)$&lt;/td&gt;
&lt;td&gt;$\theta_{pq;11}$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;各変数 $x_p$ に対して，$x_{\bar{p}} = 1 - x_{p}$ を導入し，$E(\bold x) = \sum \theta_{p}(x_p) + \sum \theta_{pq}(x_p, x_q)$ を変形します．&lt;/p&gt;
$$
\begin{alignedat}{2}
E(\bold x)
&amp;= \theta_{const} + \sum \theta_{p}(x_p)
&amp;&amp;+ \sum \theta_{pq}(x_p, x_q) \\
&amp;= \theta_{const} + \sum \big(
\theta_{p;1} x_{p} + \theta_{p;0}(1 - x_{p})
\big) \\
&amp;\quad &amp;&amp;+
\sum \big(
\theta_{pq;00} (1 - x_{p})(1 - x_{q}) \\
&amp;\quad &amp;&amp;\quad +
\theta_{pq;01} (1 - x_{p}) x_{q} \\
&amp;\quad &amp;&amp;\quad +
\theta_{pq;10} x_{p}(1 - x_{q}) \\
&amp;\quad &amp;&amp;\quad +
\theta_{pq;11} x_{p} x_{q}
\big) \\
&amp;= \theta_{const} + \sum \bigg(
\frac{\theta_{p;1}}{2}(x_p + (1 - x_{\bar{p}})) &amp;&amp;
+ \frac{\theta_{p;0}}{2}(x_{\bar{p}} + (1 - x_p))
\bigg) \\
&amp;\quad &amp;&amp;+
\sum \bigg(
\frac{\theta_{pq;00}}{2} \big(x_{\bar{p}} (1 - x_q) + (1 - x_p) x_{\bar{q}} \big) \\
&amp;\quad &amp;&amp;\quad +
\frac{\theta_{pq;01}}{2} \big((1 - x_p) x_q + x_{\bar{p}} (1 - x_{\bar{q}}) \big) \\
&amp;\quad &amp;&amp;\quad +
\frac{\theta_{pq;11}}{2} \big(x_p (1 - x_{\bar{q}}) + (1 - x_{\bar{p}}) x_q \big) \\
&amp;\quad &amp;&amp;\quad +
\frac{\theta_{pq;10}}{2} \big(x_p (1 - x_q) + (1 - x_{\bar{p}}) x_{\bar{q}} \big)
\bigg)
\end{alignedat}
$$&lt;p&gt;ここで，$x_{\bar{p}} = 1 - x_p$ という制約を緩和し，$x_p$ と $x_{\bar{p}}$ が独立に値をとれる緩和問題を考えます．&lt;br&gt;
各変数の係数を比較すると下の関数に分割できることがわかります．
再パラメータ化をしてから関数を分割することですべての関数値が $0$ 以上であることが保証されます．これらの関数は劣モジュラ関数なので「&lt;a class="link" href="#3-%e5%8a%a3%e3%83%a2%e3%82%b8%e3%83%a5%e3%83%a9%e9%96%a2%e6%95%b0%e3%81%ae%e5%a0%b4%e5%90%88" &gt;3. 劣モジュラ関数の場合&lt;/a&gt;」に帰着することができます．&lt;/p&gt;
&lt;div style="display: flex; gap: 20px;"&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$x_p$&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{p;0}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{p;1}$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$x_{\bar{p}}$&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{p;1}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{p;0}$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style="display: flex; gap: 20px;"&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$x_p$&lt;/th&gt;
&lt;th&gt;$x_q$&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{pq;01}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{pq;10}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$x_p$&lt;/th&gt;
&lt;th&gt;$x_{\bar{q}}$&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{pq;00}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{pq;11}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$x_{\bar{p}}$&lt;/th&gt;
&lt;th&gt;$x_q$&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{pq;11}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{pq;00}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$x_{\bar{p}}$&lt;/th&gt;
&lt;th&gt;$x_{\bar{q}}$&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{pq;01}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\frac{1}{2}\theta_{pq;10}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;上記関数について，ルールに従ってグラフを構築します．
整理すると以下のルールに従ってグラフを構築すればいいことがわかります．&lt;/p&gt;
&lt;div style="display: flex; gap: 20px;"&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$\theta$&lt;/th&gt;
&lt;th&gt;edge&lt;/th&gt;
&lt;th&gt;capacity&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{p;0}$&lt;/td&gt;
&lt;td&gt;$(p \rightarrow t), (s \rightarrow \bar p)$&lt;/td&gt;
&lt;td&gt;$\frac{1}{2} \theta_{p;0}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{p;1}$&lt;/td&gt;
&lt;td&gt;$(s \rightarrow p), (\bar p \rightarrow t)$&lt;/td&gt;
&lt;td&gt;$\frac{1}{2} \theta_{p;1}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq;01}$&lt;/td&gt;
&lt;td&gt;$(p \rightarrow q), (\bar q \rightarrow \bar p)$&lt;/td&gt;
&lt;td&gt;$\frac{1}{2} \theta_{pq;01}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq;10}$&lt;/td&gt;
&lt;td&gt;$(q \rightarrow p), (\bar p \rightarrow \bar q)$&lt;/td&gt;
&lt;td&gt;$\frac{1}{2} \theta_{pq;10}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq;00}$&lt;/td&gt;
&lt;td&gt;$(p \rightarrow \bar q), (q \rightarrow \bar p)$&lt;/td&gt;
&lt;td&gt;$\frac{1}{2} \theta_{pq;00}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta_{pq;11}$&lt;/td&gt;
&lt;td&gt;$(\bar q \rightarrow p), (\bar p \rightarrow q)$&lt;/td&gt;
&lt;td&gt;$\frac{1}{2} \theta_{pq;11}$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;このグラフの s-t minimum cut を計算します．各変数の値は，$S$ に属する場合は 0，$T$ に属する場合は 1 をとります．ただし，$x_{\bar{p}} = 1 - x_{p}$ という制約を満たす必要があります．よって，$\bold x$ は次のように構成されます．&lt;/p&gt;
$$
x_{p} = \left\{
\begin{array}{ll}
0 &amp; \text{if} \space p \in S, \bar p \in T \\
1 &amp; \text{if} \space p \in T, \bar p \in S \\
\emptyset &amp; \text{otherwise}
\end{array}
\right.
$$&lt;p&gt;具体例として，変数が $a$ と $b$ の 2 つだけの場合を考えます．&lt;br&gt;
各変数の値に対応する $E(\bold x) = \theta_a(a) + \theta_b(b) + \theta_{ab}(a, b)$ の値は以下のようになります．&lt;/p&gt;
&lt;div style="display: flex; gap: 20px;"&gt;
&lt;div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;a&lt;/th&gt;
&lt;th&gt;b&lt;/th&gt;
&lt;th&gt;$E(\bold x)$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{a}(0) + \theta_{b}(0) + \theta_{ab}(0, 0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{a}(0) + \theta_{b}(1) + \theta_{ab}(0, 1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$\theta_{a}(1) + \theta_{b}(0) + \theta_{ab}(1, 0)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$\theta_{a}(1) + \theta_{b}(1) + \theta_{ab}(1, 1)$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;対応するグラフは以下のようになります．表記が煩雑になるので図では $\frac{1}{2}$ を除外しています．このグラフの s-t cut の例をいくつか見ていきます．&lt;/p&gt;
&lt;img src="images/general_sample_ab.png" width="50%"&gt;
&lt;p&gt;$S = \lbrace s, a, b \rbrace$ とします．この s-t cut の容量は $\frac{1}{2} (\theta_{a}(0) + \theta_{a}(0) + \theta_{b}(0) + \theta_{b}(0) + \theta_{ab}(0, 0) + \theta_{ab}(0, 0))$ です．&lt;br&gt;
この値は $a = 0$，$b = 0$ としたときの $E(\bold x)$ の目的関数と一致します．&lt;/p&gt;
&lt;img src="images/general_sample_ab_1.png" width="50%"&gt;
&lt;p&gt;$S = \lbrace s, a \rbrace$ とします．この s-t cut の容量は $\frac{1}{2} (\theta_{a}(0) + \theta_{a}(0) + \theta_{b}(1) + \theta_{b}(1) + \theta_{ab}(0, 1) + \theta_{ab}(0, 1))$ です．&lt;br&gt;
この値は $a = 0$，$b = 0$ としたときの $E(\bold x)$ の目的関数と一致します．&lt;/p&gt;
&lt;img src="images/general_sample_ab_2.png" width="50%"&gt;
&lt;p&gt;$S = \lbrace s, a, b, \bar{b} \rbrace$ とします．この場合，$a = 0$，$b = \emptyset$ とし，$b$ のラベルは未定となります．&lt;/p&gt;
&lt;img src="images/general_sample_ab_3.png" width="50%"&gt;
&lt;h1 id="5-問題"&gt;5. 問題
&lt;/h1&gt;&lt;p&gt;QPBO を使って競プロの問題を解いていきます．&lt;/p&gt;
&lt;h2 id="arc085-e---mul"&gt;&lt;a class="link" href="https://atcoder.jp/contests/arc085/tasks/arc085_c" target="_blank" rel="noopener"
&gt;ARC085 E - MUL&lt;/a&gt;
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;宝石が $N$ 個あり，それぞれ $1,2,\cdots,N$ と数が書かれています。&lt;br&gt;
あなたは，以下の操作を好きなだけ行うことが出来ます(一度も行わなくてもよいです)。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;正整数 $x$ を選ぶ。$x$ の倍数が書かれた宝石を全て叩き割る。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そして，$i$ が書かれていた宝石が割られずに残っていた場合，$a_i$ 円貰います。 ただし，この $a_i$ は負の場合もあり，その場合はお金を払わなくてはいけません。&lt;br&gt;
うまく操作を行った時，あなたは最大で何円お金を貰えるでしょうか？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;まず変数を定義します．&lt;br&gt;
宝石 $i$ が残っているかどうかを $x_i$ で表します．宝石が割る場合 $1$ を，残す場合は $0$ をとります．&lt;/p&gt;
&lt;p&gt;次に関数を定義します．&lt;br&gt;
QPBO は目的関数値の最小化を目指すのでコストがいくらかかるかで表します．&lt;br&gt;
宝石 $i$ が残っている場合 $a_i$ 円貰えます．これは $-a_i$ 円のコストを払うということなので，次のように定義できます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\theta_{i}(0) = -a_i$&lt;/li&gt;
&lt;li&gt;$\theta_{i}(1) = 0$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また，宝石 $i$ を割るにもかかわらず $i$ で割り切れる値が書かれた宝石 $j$ を残すことは許されないので，この場合は無限のコストがかかるとします．よって，次のように定義できます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\theta_{ij}(0, 0) = 0$&lt;/li&gt;
&lt;li&gt;$\theta_{ij}(0, 1) = 0$&lt;/li&gt;
&lt;li&gt;$\theta_{ij}(1, 0) = \infty$&lt;/li&gt;
&lt;li&gt;$\theta_{ij}(1, 1) = 0$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;この関数は $\theta_{ij}(0, 1) + \theta_{ij}(1, 0) \ge \theta_{ij}(0, 0) + \theta_{ij}(1, 1)$ を満たしているので劣モジュラ関数です．&lt;br&gt;
あとは，すべての $i$ と $i$ で割り切れる $j$ について上記関数を定義すれば問題を解くことができます．&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://atcoder.jp/contests/arc085/submissions/61474030" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="abc193-f---zebraness"&gt;&lt;a class="link" href="https://atcoder.jp/contests/abc193/tasks/abc193_f" target="_blank" rel="noopener"
&gt;ABC193 F - Zebraness&lt;/a&gt;
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;縦 $N$ マス、横 $N$ マスのマス目があります。上から $i$ 行目、左から $j$ 列目のマスをマス $(i,j)$ と表すことにします。 マス $(i,j)$ の色の情報が文字 $c_{i,j}$ により与えられます。&lt;br&gt;
$B$ はマスが黒で塗られていることを、 $W$ はマスが白で塗られていることを、 $?$ はマスにまだ色が塗られていないことを表します。&lt;br&gt;
高橋くんは、まだ色が塗られていないマスをそれぞれ黒または白で塗り、白黒のマス目を作ります。マス目のしまうま度を、辺で接する黒マスと白マスの組の個数と定義します。高橋くんが達成できるしまうま度の最大値を求めてください。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;まず変数を定義します．&lt;br&gt;
マスを $(i, j)$ で表すとすると関数が見にくいので $p = i \times N + j$ で表します．
マス $p$ の色を変数 $x_{p}$ で表します．白の場合 $0$ をとり，黒の場合 $1$ をとります．&lt;/p&gt;
&lt;p&gt;次に関数を定義します．&lt;br&gt;
与えられている色の変更はできないので白から黒や黒から白に変更すると無限のコストがかかるとします．次のように定義できます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;マス $p$ の色が黒の場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\theta_{p}(0) = \infty$&lt;/li&gt;
&lt;li&gt;$\theta_{p}(1) = 0$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;マス $p$ の色が白の場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\theta_{p}(0) = 0$&lt;/li&gt;
&lt;li&gt;$\theta_{p}(1) = \infty$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;マス $p$ と辺で接するマス $q$ が異なる色だと -1 のコストがかかります．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\theta_{pq}(0, 0) = 0$&lt;/li&gt;
&lt;li&gt;$\theta_{pq}(0, 1) = -1$&lt;/li&gt;
&lt;li&gt;$\theta_{pq}(1, 0) = -1$&lt;/li&gt;
&lt;li&gt;$\theta_{pq}(1, 1) = 0$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これは劣モジュラ関数ではないのですが，変数フリップすることで劣モジュラ関数にすることができます．
QPBO 法では変数フリップを考慮しなくていいのでそのまま定義することができます．&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://atcoder.jp/contests/abc193/submissions/61474153" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="その他の問題"&gt;その他の問題
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://yukicoder.me/problems/no/2713" target="_blank" rel="noopener"
&gt;No.2713 Just Solitaire&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://yukicoder.me/submissions/1034571" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2903" target="_blank" rel="noopener"
&gt;AOJ - Board&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=10082476#1" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://onlinejudge.u-aizu.ac.jp/challenges/sources/UOA/UAPC/3058" target="_blank" rel="noopener"
&gt;AOJ - Ghost&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://onlinejudge.u-aizu.ac.jp/solutions/problem/3058/review/10082488/MitI7/C&amp;#43;&amp;#43;23" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://atcoder.jp/contests/typical90/tasks/typical90_an" target="_blank" rel="noopener"
&gt;競プロ典型 90 問 040 - Get More Money（★7）&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://atcoder.jp/contests/typical90/submissions/61474485" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://atcoder.jp/contests/abc259/tasks/abc259_g" target="_blank" rel="noopener"
&gt;ABC259 G - Grid Card Game&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://atcoder.jp/contests/abc259/submissions/61474556" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="参考"&gt;参考
&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://ieeexplore.ieee.org/document/4204169" target="_blank" rel="noopener"
&gt;Minimizing non-submodular functions with graph cuts – a review&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.kspub.co.jp/book/detail/1529090.html" target="_blank" rel="noopener"
&gt;劣モジュラ最適化と機械学習&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://en.wikipedia.org/wiki/Graph_cut_optimization" target="_blank" rel="noopener"
&gt;Graph cut optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://en.wikipedia.org/wiki/Quadratic_pseudo-Boolean_optimization" target="_blank" rel="noopener"
&gt;Quadratic pseudo-Boolean optimization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;たぶんです．できない例があったら教えてください&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;この数値例は&lt;a class="link" href="https://ja.wikipedia.org/wiki/%E6%9C%80%E5%A4%A7%E3%83%95%E3%83%AD%E3%83%BC%E6%9C%80%E5%B0%8F%E3%82%AB%E3%83%83%E3%83%88%E5%AE%9A%E7%90%86#/media/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:Max_flow.svg" target="_blank" rel="noopener"
&gt;最大フロー最小カット定理&lt;/a&gt;から引用しています&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;標準形は一意に定まるとは限りません&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;単純な関数の場合は劣モジュラ関数を(ほぼ)標準化したものでした．厳密には $min \lbrace \theta_{p;0}, \theta_{p;1} \rbrace = 0$ を満たしていませんが．&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;Minimizing non-submodular functions with graph cuts – a review&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;実装では容量に $\frac{1}{2}$ をかけるのではなく，最後に目的関数値に $\frac{1}{2}$ を掛ければいいです&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Kinesis Advantage 360 Pro の設定</title><link>https://miti-7.github.io/post/kinesis-advantage-360-pro-%E3%81%AE%E8%A8%AD%E5%AE%9A/</link><pubDate>Sat, 26 Oct 2024 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/kinesis-advantage-360-pro-%E3%81%AE%E8%A8%AD%E5%AE%9A/</guid><description>&lt;h2 id="設定"&gt;設定
&lt;/h2&gt;&lt;p&gt;Kinesis Advantage 360 Pro の設定をメモしておきます&lt;/p&gt;
&lt;h2 id="バックライト"&gt;バックライト
&lt;/h2&gt;&lt;p&gt;デフォルトだと「Mod + Enter」で on/off，「Mod + ↑/↓」で明るさの調整ができる&lt;br&gt;
バックライトをつけておくとすぐにバッテリーがなくなるらしいので off にした&lt;/p&gt;
&lt;h2 id="keymap"&gt;Keymap
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://kinesiscorporation.github.io/Adv360-Pro-GUI/" target="_blank" rel="noopener"
&gt;Kinesis ADV360 Pro Keymap Editor&lt;/a&gt; で設定できる．&lt;/p&gt;
&lt;img src="images/Layer1.png" width="100%"&gt;
&lt;ul&gt;
&lt;li&gt;Windows キーはあまりつかわないので ALT を配置
&lt;ul&gt;
&lt;li&gt;代わりに Caps を Windwos キーにした&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;PgUp を ESC に，PgDn を 「CTRL + PG_DN」 にした
&lt;ul&gt;
&lt;li&gt;「CTRL + PG_DN」 で IME の切り替えをしているので&lt;/li&gt;
&lt;li&gt;「LC」を選ぶと，LCTRL + PG_DN を選択できる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;① と ② は迷い中&lt;/li&gt;
&lt;li&gt;③ と ④ に PG_UP と PG_DN を配置&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/Layer2.png" width="100%"&gt;
&lt;ul&gt;
&lt;li&gt;キーキャップの数字とファンクションキーがずれていて迷うので数字と同じになるようにひとつずらした
&lt;ul&gt;
&lt;li&gt;F12 と F13 の位置がひどいことになった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="バッテリー"&gt;バッテリー
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;バックライトをオフにしていると 数ヶ月はもつらしい&lt;/li&gt;
&lt;li&gt;「Mod + ④」で充電レベルを確認できる
&lt;ul&gt;
&lt;li&gt;Green: 80% 以上&lt;/li&gt;
&lt;li&gt;Yellow: 51% - 79%&lt;/li&gt;
&lt;li&gt;Orange: 21% - 50%&lt;/li&gt;
&lt;li&gt;Red: 20% 以下&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="高さ"&gt;高さ
&lt;/h2&gt;&lt;p&gt;LOW/MEDIUM/HIGH の 3 段階に調整できる&lt;br&gt;
今は MEDIUM を使っている&lt;/p&gt;
&lt;h2 id="bluetooth-の接続や遅延"&gt;Bluetooth の接続や遅延
&lt;/h2&gt;&lt;p&gt;特に問題なく使えている&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kinesis-ergo.com/support/kb360pro/" target="_blank" rel="noopener"
&gt;Advantage 360 Professional (ZMK Bluetooth) Support Resources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>最小費用流問題の最短路繰り返し法</title><link>https://miti-7.github.io/post/minimum-cost-flow-successive-shortest-path/</link><pubDate>Mon, 21 Oct 2024 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/minimum-cost-flow-successive-shortest-path/</guid><description>&lt;h2 id="最小費用流問題minimum-cost-flow-problem"&gt;最小費用流問題(Minimum Cost Flow Problem)
&lt;/h2&gt;&lt;p&gt;$N$ を頂点の集合，$A$ を辺の集合，$c_{ij}$ を辺 $(i, j)$ の単位流量あたりのコスト，$x_{ij}$ を辺 $(i, j)$ の流量，$b_i$ を頂点 i の需要/供給量，$l$ を辺の下限容量，$u$ を辺の上限容量としたとき，最小費用流問題（以下 MCFP）は以下のように定式化されます．&lt;br&gt;
1 つめの制約を流量保存則と呼び，第一項は頂点 $i$ から出る流量，第二項は頂点 $i$ に入る流量を表します．
2 つめの制約を容量制約と呼びます．&lt;/p&gt;
$$
\begin{aligned}
&amp;\text{minimize} &amp;&amp; \sum_{(i, j) \in A} c_{ij} x_{ij} \\
&amp;\text{subject to}
&amp;&amp; \sum_{j:(i, j) \in A} x_{ij} - \sum_{j:(j,i) \in A} x_{ji} = b_i &amp;&amp; \forall i \in N \\
&amp; &amp;&amp; l_{ij} \le x_{ij} \leq u_{ij} &amp;&amp; \forall (i, j) \in A
\end{aligned}
$$&lt;p&gt;以下ではコスト，流量，需要/供給，下限容量，上限容量はすべて整数とします．また，$\sum_{i \in N} b_i = 0$，コストを非負，下限容量を $0$ とします．&lt;/p&gt;
&lt;h2 id="用語定義"&gt;用語・定義
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;pseudoflow&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;容量制約を満たす flow を pseudoflow と呼びます．流量保存則には違反していてもかまいません．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;残余容量&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$r_{ij} = u_{ij} - x_{ij}$ を辺 (i, j) の残余容量と呼びます．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;imbalance&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pseudoflow $\bold x$ に対し，頂点 $i$ の imbalance を次のように定義します．第 2 項は $i$ に入ってくる流量の合計，第 3 項は $i$ から出ていく流量の合計です．&lt;br&gt;
$e(i) = b(i) + \sum_{j:(j, i) \in A} x_{ji} - \sum_{j:(i,j) \in A} x_{ij}$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;reduced cost&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;各頂点のポテンシャル $\bold \pi$ が与えられたとき，$c_{ij}^{\pi} = c_{ij} - \pi(i) + \pi(j)$ を辺 (i, j) の reduced cost と呼びます．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="reduced-cost-最適性"&gt;Reduced Cost 最適性
&lt;/h2&gt;&lt;p&gt;最小費用流問題の実行可能な flow $\bold x$ が最適であるための必要十分条件は，残余ネットワークのすべての辺 (i, j) に対して$c^{\pi}_{ij} \ge 0$ となるポテンシャル $\bold \pi$ が存在することです．&lt;/p&gt;
&lt;h2 id="最短路繰り返し法successive-shortest-path-algorithm"&gt;最短路繰り返し法(Successive Shortest Path Algorithm)
&lt;/h2&gt;&lt;p&gt;最短路繰り返し法は，容量制約を満たすが流量保存則に違反する pseudoflow $\bold x$ から開始します．&lt;br&gt;
アルゴリズムの各ステップでは reduced cost 最適性を維持しつつ，主問題の実行不能解 $\bold x$ を実行可能解に近づけます．&lt;br&gt;
具体的には，残余ネットワーク上で $e(k) \gt 0$ である頂点 $k$ から $e(l) \lt 0$ である頂点 $l$ へ，最短路に沿って flow を流すことで実行可能性を高めていきます．&lt;br&gt;
実行可能解が得られたときアルゴリズムは終了します．&lt;/p&gt;
&lt;p&gt;最短路繰り返し法の流れは以下のようになります&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;初期解の構築
&lt;ul&gt;
&lt;li&gt;$\bold x = \bold 0$，$\bold \pi = \bold 0$ とする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;実行可能解が得られるまで以下を繰り返す
&lt;ul&gt;
&lt;li&gt;$e(k) \gt 0$ である頂点 $k$ を選ぶ．各辺の reduced cost を距離とする残余ネットワーク上で，$k$ から各頂点への最短路を求める．$\bold P$ を $k$ から各頂点への最短路，$\bold d$ を最短距離とする&lt;/li&gt;
&lt;li&gt;ポテンシャルの更新
&lt;ul&gt;
&lt;li&gt;$\bold \pi^{\prime} = \bold \pi - \bold d$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;flow の更新
&lt;ul&gt;
&lt;li&gt;$\delta = min[e(k), min(r_{ij} : (i,j) \in P)]$とし，$\bold P$ に沿って辺の flow を $\delta$ 増加する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;imbalance の更新
&lt;ul&gt;
&lt;li&gt;$e(k) = e(k) - \delta$，$e(l) = e(l) + \delta$ と更新する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;次節からアルゴリズムの各ステップで常に reduced cost 最適性を維持することを確認していきます．&lt;/p&gt;
&lt;h2 id="初期解の構築"&gt;初期解の構築
&lt;/h2&gt;&lt;p&gt;初期解が容量制約と reduced cost 最適性を満たすことを確認します．&lt;br&gt;
仮定より，下限容量は $0$ のため $\bold x = \bold 0$ は容量制約を満たします．&lt;br&gt;
$\bold \pi = \bold 0$ のため $c_{ij}^{\pi} = c_{ij}$ です．辺のコストはすべて非負を仮定しているため $c_{ij}^{\pi} \ge 0$ となり reduced cost 最適性を満たします．&lt;/p&gt;
&lt;h2 id="ポテンシャルの更新"&gt;ポテンシャルの更新
&lt;/h2&gt;&lt;p&gt;ある $\bold x$ に対し $\bold \pi$ が reduced cost 最適性を満たしているとき，ポテンシャルを $\bold \pi^{\prime} = \bold \pi - \bold d$ と更新しても reduced cost 最適性を満たすことを示します&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;．&lt;/p&gt;
&lt;p&gt;$\bold d$ は reduced cost を距離とした残余ネットワーク上での頂点 $k$ から各頂点への最短距離であるため，各辺 (i, j) は $d(j) \le d(i) + c_{ij}^{\pi}$ を満たします．&lt;/p&gt;
&lt;p&gt;上の式に $c_{ij}^{\pi} = c_{ij} - \pi(i) + \pi(j)$ を代入します．&lt;br&gt;
$d(j) \le d(i) + c_{ij} - \pi(i) + \pi(j)$&lt;/p&gt;
&lt;p&gt;$d(j)$を移項し，頂点ごとにまとめます．&lt;br&gt;
$c_{ij} - (\pi(i) - d(i)) + (\pi(j) - d(j)) \ge 0$&lt;/p&gt;
&lt;p&gt;ポテンシャルの更新の仕方から以下が成り立ちます．&lt;br&gt;
$c_{ij} - \pi^{\prime}(i) + \pi^{\prime}(j) = c^{\pi_{ij}^{\prime}} \ge 0$&lt;/p&gt;
&lt;p&gt;よって，ポテンシャルを $\bold \pi^{\prime} = \bold \pi - \bold d$ と更新しても reduced cost 最適性を満たすことがわかりました．&lt;/p&gt;
&lt;h2 id="flow-の更新"&gt;flow の更新
&lt;/h2&gt;&lt;p&gt;最短路に沿って flow を更新したとき reduced cost 最適性を満たすことを確認します．&lt;/p&gt;
&lt;p&gt;まず，ポテンシャルを $\bold \pi^{\prime} = \bold \pi - \bold d$ と更新したとき，頂点 $k$ から各頂点への最短路の辺の reduced cost が $0$ となることを確認します．&lt;br&gt;
頂点 $k$ から頂点 $l$ の最短路を考えます．最短路であるため，この経路の各辺は $d(j) = d(i) + c_{ij}^{\pi}$ を満たします．&lt;/p&gt;
&lt;p&gt;上の式に $c_{ij}^{\pi} = c_{ij} - \pi(i) + \pi(j)$ を代入します．&lt;br&gt;
$d(j) = d(i) + c_{ij} - \pi(i) + \pi(j)$&lt;/p&gt;
&lt;p&gt;$d(j)$ を移項し，頂点ごとにまとめます．&lt;br&gt;
$c_{ij} - (\pi(i) - d(i)) + (\pi(j) - d(j)) = 0$&lt;/p&gt;
&lt;p&gt;ポテンシャルの更新の仕方から以下が成り立ちます．&lt;br&gt;
$c_{ij} - \pi^{\prime}(i) + \pi^{\prime}(j) = c^{\pi_{ij}^{\prime}} = 0$&lt;/p&gt;
&lt;p&gt;よって，頂点 $k$ から各頂点への最短路の辺の reduced cost は $0$ となることがわかりました．&lt;/p&gt;
&lt;p&gt;次に，flow を更新したとき reduced cost 最適性を満たすことを確認します．&lt;br&gt;
$\delta = min[e(s), min(r_{ij} : (i,j) \in P)]$ とし，最短路に沿って辺の flow を更新します．&lt;br&gt;
$\delta$ 選び方から，このように flow を更新しても容量制約を満たします．また，reduced cost が $0$ であるため，辺に flow を流すことで残余ネットワーク上に逆辺が生じたとしても reduced cost 最適性には違反しません．&lt;br&gt;
よって，最短路に沿って flow を更新したとき reduced cost 最適性を満たすことがわかりました．&lt;/p&gt;
&lt;h2 id="計算量"&gt;計算量
&lt;/h2&gt;&lt;p&gt;$U$ を最大の供給量，$C$ をコストの最大値とします．&lt;br&gt;
アルゴリズムは各イテレーションで最短路問題を解き，供給量は厳密に減少します．
よって，$nU$ 回のイテレーションでアルゴリズムは終了します．最短路問題に 2 分ヒープを使った dijkstra 法を使うとすると $O((m + n) \log n)$ となります．&lt;br&gt;
よって，全体で $O(nU (m + n) \log n)$ となります．&lt;/p&gt;
&lt;h2 id="補足ポテンシャルの更新の改善"&gt;補足：ポテンシャルの更新の改善
&lt;/h2&gt;&lt;p&gt;上記のアルゴリズムの説明では頂点 $k$ からすべての頂点に対する最短路を求めましたが，$e(l) \lt 0$ のような頂点を見つけたとき探索を終了することができます．&lt;br&gt;
dijkstra 法で最短距離を求めているとします．最短距離が確定した頂点を permanently labeled node，まだ確定していない頂点を temporarily labeled node と呼びます．&lt;br&gt;
このとき，ポテンシャルは以下のように更新することができます．&lt;/p&gt;
$$
\pi^{\prime} = \left\{
\begin{array}{ll}
\pi_{i} - d_{i} &amp; \text{node i is permanently labeled}\\
\pi_{i} - d_{l} &amp; \text{node i is temporarily labeled}
\end{array}
\right.
$$&lt;details&gt;
&lt;summary&gt;証明&lt;/summary&gt;
$S$ を permanently labeled node の集合，$\bar{S}$ を temporarily labeled node の集合とします．
頂点 $i$ と頂点 $j$ が $S$ と $T$ のどちらに属するかの 4 つ場合について，ポテンシャルが $\boldd \pi$ から $\bold \pi^{\prime}$ に変更されたときを考えます．
&lt;h3 id="1--の場合"&gt;1. $i \in S, j \in S$ の場合
&lt;/h3&gt;&lt;p&gt;「ポテンシャルの更新」の節と同じです．&lt;/p&gt;
&lt;h3 id="2--の場合"&gt;2. $i \in S, j \in \bar{S}$ の場合
&lt;/h3&gt;&lt;p&gt;$c^{\pi^{\prime}} = c_{ij}^{\pi} + d(i) - d(l)$ と更新されます．&lt;br&gt;
頂点 $j$ は最短距離と確定していないため，$d(l) \le d(j)$ です．&lt;br&gt;
また，頂点 $i$ は最短距離と確定しているため，dijkstra 法のアルゴリズムから $d(j) \le d(i) + c_{ij}^{\pi}$ が成り立ちます．&lt;br&gt;
よって，$d(l) \le d(i) + c_{ij}^{\pi}$ であるため $c_{ij}^{\pi^{\prime}} \ge 0$ を満たします．&lt;/p&gt;
&lt;h3 id="3--の場合"&gt;3. $i \in \bar{S}, j \in S$ の場合
&lt;/h3&gt;&lt;p&gt;$c^{\pi^{\prime}} = c_{ij}^{\pi} + d(l) - d(j)$ と更新されます．&lt;br&gt;
頂点 $j$ は最短距離と確定しているため，$d(j) \le d(l)$ です．&lt;br&gt;
よって，$c\_{ij}^{\pi^{\prime}} \ge 0$ を満たします．&lt;/p&gt;
&lt;h3 id="4--の場合"&gt;4. $i \in \bar{S}, j \in \bar{S}$ の場合
&lt;/h3&gt;&lt;p&gt;$c^{\pi^{\prime}} = c_{ij}^{\pi} + d(l) - d(l)$ と更新されます．&lt;br&gt;
よって，$c_{ij}^{\pi} \ge 0$ を満たします．&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;また，すべてのポテンシャルに定数を加算しても reduced cost 最適性に影響はないため，全体に $d(l)$ を加算することで以下のように更新することもできます．&lt;/p&gt;
$$
\pi^{\prime} = \left\{
\begin{array}{ll}
\pi_{i} - d_{i} + d_{l} &amp; \text{node i is permanently labeled}\\
\pi_{i} &amp; \text{node i is temporarily labeled}
\end{array}
\right.
$$&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.amazon.co.jp/dp/1292042702" target="_blank" rel="noopener"
&gt;Network Flows: Pearson New International Edition&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;すべての頂点の距離が定まることを仮定しています．&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>最短路問題の最適性条件と reduced arc length</title><link>https://miti-7.github.io/post/shortest-path-optimality-condition-reduced-arc-length/</link><pubDate>Tue, 17 Sep 2024 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/shortest-path-optimality-condition-reduced-arc-length/</guid><description>&lt;h2 id="最短路問題"&gt;最短路問題
&lt;/h2&gt;&lt;p&gt;有向グラフが与えられたとき，始点 s から各頂点への最短路を求める問題を単一始点最短路問題といいます．以下では，頂点数を $n$，辺数を $m$，各辺 (u, v) のコストを $c_{uv}$ で表します．また，グラフは強連結を仮定します．&lt;/p&gt;
&lt;h2 id="最短路問題の最適性条件"&gt;最短路問題の最適性条件
&lt;/h2&gt;&lt;p&gt;頂点集合を $N$，辺集合を $A$，辺 (u, v) のコストを $c_{uv}$ とします．始点 s から各頂点 v への有向パスの距離の上界を $d(v)$ で表し，これを距離ラベルと呼びます．特に，$d(s) = 0$ です．各頂点 $v \in N$ について，$d(v)$ が始点 s から頂点 v の最短路の長さであるための必要十分条件は以下が成り立つことです．&lt;/p&gt;
$$
\begin{equation}
d(v) \le d(u) + c_{uv} \quad \forall (u, v) \in A
\end{equation}
$$&lt;p&gt;不等式 (1) は，各辺 $(u, v) \in A$ について，頂点 v への距離は頂点 u への距離 + $c_{uv}$ 以下であることを表しています．&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;証明&lt;/summary&gt;
&lt;p&gt;まず，必要条件であることを示します．&lt;br&gt;
対偶をとり，$d(v) \gt d(u) + c_{uv}$ ならば，距離ラベルが最短路の長さではないことを示します．&lt;br&gt;
$d(v) \gt d(u) + c_{uv}$ であるような辺があれば，頂点 u を経由することで頂点 v への距離を改善することができます．&lt;br&gt;
したがって，距離ラベル $d$ は最短路の長さではありません．&lt;/p&gt;
&lt;p&gt;次に，十分条件であることを示します．&lt;br&gt;
頂点 s から頂点 v への任意の有向パスが $s = i_1 \rightarrow i_2 \rightarrow ... \rightarrow i_{k-1} \rightarrow i_k = v$ であったとします．&lt;br&gt;
不等式 (1) から以下の式がそれぞれ成り立ちます．&lt;/p&gt;
$$
\begin{aligned}
d(v) =\; &amp; d(i_k) &amp;&amp; \le\; d(i_{k - 1}) &amp;&amp; +\; c_{i_{k - 1}i_{k}}, \\
&amp; d(i_{k - 1}) &amp;&amp; \le\; d(i_{k - 2}) &amp;&amp; +\; c_{i_{k - 2} i_{k - 1}}, \\
&amp; \vdots \\
&amp; d(i_{2}) &amp;&amp; \le\; d(i_{1}) &amp;&amp; +\; c_{i_{1}i_{2}} = c_{i_{1}i_{2}}.
\end{aligned}
$$&lt;p&gt;式をそれぞれ代入すると&lt;/p&gt;
$$
d(v) = d(i_{k}) \le c_{i_{k-1}i_{k}} + c_{i_{k-2}i_{k-1}} + \dots + c_{i_{1}i_{2}} = \sum_{(u, v) \in P} c_{uv}
$$&lt;p&gt;となり，$d(v)$ は，始点 s から頂点 v への任意の有向パスのコストの合計の下界になります．
$d(v)$ は始点 s から頂点 v への任意の有向パスの下界かつ上界なので，距離ラベル $d(v)$ は最短路の長さです．&lt;/p&gt;
&lt;p&gt;以上のことから，「各頂点 $v \in N$ について距離ラベル $d(v)$ が最短路の長さである」の必要十分条件は，「各辺 $(u, v) \in A$ について $d(v) \le d(u) + c_{uv}$ を満たす」であることがわかりました．&lt;/p&gt;
&lt;/details&gt;
&lt;h2 id="reduced-arc-length-の性質"&gt;reduced arc length の性質
&lt;/h2&gt;&lt;p&gt;ある距離ラベル $d$ に対し，$c_{uv}^{d} = c_{uv} + d(u) - d(v)$ を reduced arc length と呼びます．reduced arc length には次の性質があります．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;任意の閉路 $W$ について，$\sum_{(u, v) \in W} c_{uv}^{d} = \sum_{(u, v) \in W} c_{uv}$&lt;/li&gt;
&lt;li&gt;頂点 k から頂点 l への任意の有向パス $P$ について，$\sum_{(u, v) \in P} c_{uv}^{d} = \sum_{(u, v) \in P} c_{uv} + d(k) - d(l)$&lt;/li&gt;
&lt;li&gt;距離ラベル $d$ が最適ならば，すべての辺 (u, v) について $c_{uv}^{d} \ge 0$ が成り立つ&lt;/li&gt;
&lt;/ol&gt;
&lt;details&gt;&lt;summary&gt;性質 1 の証明&lt;/summary&gt;
$$
\begin{aligned}
\sum_{(u, v) \in W} c_{uv}^{d} &amp;= \sum_{(u, v) \in W} (c_{uv} + d(u) - d(v)) \\
&amp;= \sum_{(u, v) \in W} c_{uv} + \sum_{(u, v) \in W} (d(u) - d(v)) \\
&amp;= \sum_{(u, v) \in W} c_{uv} \\
\end{aligned}
$$&lt;p&gt;任意の有向閉路 $W$ において，頂点 u は $+d(u)$としてちょうど 1 回，$-d(u)$ としてちょうど 1 回出現するため，$\sum_{(u, v) \in W} (d(u) - d(v)) = 0$ が成り立ちます．&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;性質 2 の証明&lt;/summary&gt;
$$
\begin{aligned}
\sum_{(u, v) \in P} c_{uv}^{d} &amp;= \sum_{(u, v) \in P} (c_{uv} + d(u) - d(v)) \\
&amp;= \sum_{(u, v) \in P} c_{uv} + \sum_{(u, v) \in P} (d(u) - d(v)) \\
&amp;= \sum_{(u, v) \in P} c_{uv} + d(k) - d(l) \\
\end{aligned}
$$&lt;p&gt;頂点 k と頂点 l 以外の頂点は，$+d(u)$ としてちょうど 1 回，$-d(u)$ としてちょうど 1 回出現するため互いに打ち消し合います．&lt;br&gt;
頂点 k は $+d(k)$ として，頂点 $l$ は $-d(l)$ としてちょうど 1 回出現します．&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;性質 3 の証明&lt;/summary&gt;
最適性条件から直ちに言えます
&lt;/details&gt;
&lt;p&gt;次節からは，reduced arc length の性質を使ったアルゴリズムと問題を見ていきます．&lt;/p&gt;
&lt;h2 id="johnsons-algorithm"&gt;Johnson&amp;rsquo;s algorithm
&lt;/h2&gt;&lt;p&gt;任意の 2 頂点の組 (u, v) に対して頂点 u から頂点 v の最短路を求める問題を全点対最短路問題と呼びます．&lt;br&gt;
Johnson&amp;rsquo;s algorithm は全点対最短路問題を解くアルゴリズムです．&lt;/p&gt;
&lt;p&gt;頂点数が $n$ のとき，単一始点最短路問題を n 回解くことによって全点対最短路を求めることができます．&lt;br&gt;
ただし，グラフにコストが負の辺があると，単一始点最路問題を解くのに Dijkstra 法を使うことができません．そこで，グラフのコストを reduced arc length に変換したグラフ上で最短路を求めることにします．reduced arc length の性質 3 から，最適距離ラベル $d$ に対する reduced arc length のコストはすべて 0 以上であるため Dijkstra 法を使うことができます．&lt;br&gt;
変換したグラフ上で最短距離を求めたあと，性質 2 を使って元のグラフの距離に変換します．&lt;br&gt;
最適距離ラベルは Bellman–Ford 法を使い求めることができます．負閉路が見つかった場合はアルゴリズムを終了します．&lt;/p&gt;
&lt;p&gt;Dijkstra 法に二分ヒープを使うとき，Bellman–Ford 法に $O(nm)$，Dijkstra 法に $O((n + m) \log n)$ かかるため，計算量は全体として $O(nm + n ((n + m) \log n))$ となります．&lt;/p&gt;
&lt;p&gt;例として，&lt;a class="link" href="https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C&amp;amp;lang=ja" target="_blank" rel="noopener"
&gt;AOJ - All Pairs Shortest Path&lt;/a&gt; を解きます．&lt;br&gt;
与えられるグラフは強連結ではないため，人工頂点 s を追加し，s から他のすべての頂点に重さ 0 の辺を張ります．この s を始点として Bellman-Ford 法を使うことで最適距離ラベルを求めることができます．&lt;br&gt;
実装では人工頂点を追加するのではなく， Bellman-Ford の初期解をすべて 0 とすることで対応しています．&lt;br&gt;
&lt;a class="link" href="https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=9647270#1" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="abc237-e---skiing"&gt;&lt;a class="link" href="https://atcoder.jp/contests/abc237/tasks/abc237_e" target="_blank" rel="noopener"
&gt;ABC237 E - Skiing&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;問題概要&lt;br&gt;
$N$ 頂点，$M$ 辺の強連結の有向グラフと各頂点 u の高さ $H(u)$ が与えられる．$H(u) \ge H(v)$ としたとき，頂点 u から頂点 v にはコスト $H(v) - H(u)$ の辺が，頂点 v から頂点 u にはコスト $2(H(u) - H(v))$ の辺が張られている．頂点 1 から各頂点への最短距離の中で最も小さいものを求めよ．&lt;/p&gt;
&lt;p&gt;負辺のあるグラフの最短路問題なので Bellman–Ford 法を使えば答えが求まりますが，Bellman–Ford 法の計算量は $O(nm)$ なので TLE になってしまいます．
そこで，グラフのコストを reduced arc length に変換したグラフ上で最短路を求めることにします．&lt;/p&gt;
&lt;p&gt;まず，不等式 (1) を満たすような距離ラベルを考えます．&lt;br&gt;
ある距離ラベル $d$ に対して，$H(u) \ge H(v)$ のとき，$c_{uv}^{d}$ と $c_{vu}^{d}$ は以下のように表せます．&lt;/p&gt;
$$
\begin{aligned}
c_{uv}^{d} &amp;= c_{uv} + d(u) - d(v) = H(v) - H(u) + d(u) - d(v) \\
c_{vu}^{d} &amp;= c_{vu} + d(v) - d(u) = 2(H(u)- H(v)) + d(v) - d(u) \\
\end{aligned}
$$&lt;p&gt;u と v についてまとめて式を整理します．&lt;/p&gt;
$$
\begin{aligned}
c_{uv}^{d} &amp;= (H(v) - d(v)) - (H(u) - d(u)) \\
c_{vu}^{d} &amp;= (2H(u) - d(u)) - (2H(v) - d(v)) \\
\end{aligned}
$$&lt;p&gt;$c_{uv}^{d} \ge 0$ かつ $c_{vu}^{d} \ge 0$ にしたいので，各頂点 u について $d(u) = H(u)$ とすると以下のようになります．&lt;/p&gt;
$$
\begin{aligned}
c_{uv}^{d} &amp;= (H(v) - H(v)) - (H(u) - H(u)) = 0 \\
c_{vu}^{d} &amp;= (2H(u) - H(u)) - (2H(v) - H(v)) = H(u) - H(v)\\
\end{aligned}
$$&lt;p&gt;以上のことから，次のように問題を言い換えることができます．&lt;br&gt;
$N$ 頂点，$M$ 辺の強連結の有向グラフと各頂点 u の高さ $H(u)$ が与えられる．$H(u) \ge H(v)$ のとき，頂点 u から頂点 v にはコスト 0 の辺が，頂点 v から頂点 u にはコスト $H(u) - H(v)$ の辺が張られている．頂点 1 から各頂点への最短距離の中で最も小さいものを求めよ．&lt;/p&gt;
&lt;p&gt;すべての辺のコストは 0 以上なので Dijkstra 法で求めることができます．&lt;br&gt;
求まる値は変換したグラフ上での値なので，$distance[u] - H[0] + H[u]$ として元のグラフ上での値に戻します．&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://atcoder.jp/contests/abc237/submissions/57838602" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.amazon.co.jp/dp/1292042702" target="_blank" rel="noopener"
&gt;Network Flows: Pearson New International Edition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://en.wikipedia.org/wiki/Johnson%27s_algorithm" target="_blank" rel="noopener"
&gt;Johnson&amp;rsquo;s algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://atcoder.jp/contests/abc237/editorial/3339" target="_blank" rel="noopener"
&gt;E - Skiing 解説&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>HUGO でファイル変更が検出されないときの対処</title><link>https://miti-7.github.io/post/hugo-%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%A4%89%E6%9B%B4%E3%81%8C%E6%A4%9C%E5%87%BA%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84%E3%81%A8%E3%81%8D%E3%81%AE%E5%AF%BE%E5%87%A6/</link><pubDate>Sun, 15 Sep 2024 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/hugo-%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%A4%89%E6%9B%B4%E3%81%8C%E6%A4%9C%E5%87%BA%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84%E3%81%A8%E3%81%8D%E3%81%AE%E5%AF%BE%E5%87%A6/</guid><description>&lt;p&gt;hugo ではサーバーの実行中にファイルが変更されるとサイトを再構築し自動的にブラウザを更新してくれる機能があるのですが
，&lt;a class="link" href="https://gohugo.io/troubleshooting/faq/#why-isnt-hugos-development-server-detecting-file-changes" target="_blank" rel="noopener"
&gt;Frequently asked questions&lt;/a&gt; によると WSL で実行しているときはうまく動作しないことがあるらしいです．&lt;br&gt;
このようなときは server を起動するときに，&lt;a class="link" href="https://gohugo.io/commands/hugo_server/" target="_blank" rel="noopener"
&gt;poll オプション&lt;/a&gt;を指定すると定期的にポーリングしてくれます．&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server --poll &amp;#34;700ms&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>最小費用流問題の Primal Network Simplex 法</title><link>https://miti-7.github.io/post/minimum-cost-flow-primal-network-simplex/</link><pubDate>Wed, 11 Sep 2024 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/minimum-cost-flow-primal-network-simplex/</guid><description>&lt;img src="https://miti-7.github.io/post/minimum-cost-flow-primal-network-simplex/images/%E3%83%9D%E3%83%86%E3%83%B3%E3%82%B7%E3%83%A3%E3%83%AB%E3%81%AE%E6%9B%B4%E6%96%B0.png" alt="Featured image of post 最小費用流問題の Primal Network Simplex 法" /&gt;&lt;h2 id="最小費用流問題minimum-cost-flow-problem"&gt;最小費用流問題(Minimum Cost Flow Problem)
&lt;/h2&gt;&lt;p&gt;$N$ を頂点の集合，$A$ を辺の集合，$c_{ij}$ を辺 $(i, j)$ の単位流量あたりのコスト，$x_{ij}$ を辺 $(i, j)$ の流量，$b_i$ を頂点 i の需要/供給量，$l$ を辺の下限容量，$u$ を辺の上限容量としたとき，最小費用流問題（以下 MCFP）は以下のように定式化されます．&lt;br&gt;
1 つめの制約を流量保存則と呼び，第一項は頂点 i から出る流量，第二項は頂点 i に入る流量を表します．
2 つめの制約を容量制約と呼びます．&lt;/p&gt;
$$
\begin{aligned}
&amp;\text{minimize} &amp;&amp; \sum_{(i, j) \in A} c_{ij} x_{ij} \\
&amp;\text{subject to}
&amp;&amp; \sum_{j:(i, j) \in A} x_{ij} - \sum_{j:(j,i) \in A} x_{ji} = b_i &amp;&amp; \forall i \in N \\
&amp; &amp;&amp; l_{ij} \le x_{ij} \leq u_{ij} &amp;&amp; \forall (i, j) \in A
\end{aligned}
$$&lt;p&gt;以下ではコスト，流量，需要/供給，下限容量，上限容量はすべて整数とします．また，$\sum_{i \in N} b_i = 0$ を仮定します．&lt;/p&gt;
&lt;h2 id="primal-network-simplex-法"&gt;Primal Network Simplex 法
&lt;/h2&gt;&lt;p&gt;primal network simplex 法は，ネットワーク構造を利用することで simplex 法を効率化させたアルゴリズムです．今回は primal network simplex 法で MCFP を解いていきます．&lt;br&gt;
MCFP が必ず 最適 spanning tree solution という解を持つことを利用し，spanning tree solution のみを探索することで効率的に最適解を見つけることができます&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;．&lt;/p&gt;
&lt;p&gt;primal network simplex 法は，simplex 法の観点と負閉路除去法の観点から説明することができますが，今回は負閉路除去法の観点で説明します．
節 1 で spanning tree solution の定義をします．節 2 で spanning tree solution は spanning tree structure として表せることと，spanning tree structure が最適解となる条件について示します．節 3 で primal network simplex 法の流れについて説明し，節 4 から 節 8 でアルゴリズムの各段階の詳細について述べます．節 9 から節 11 で退化について説明します．&lt;/p&gt;
&lt;h2 id="1-spanning-tree-solution"&gt;1. spanning tree solution
&lt;/h2&gt;&lt;p&gt;ある実行可能解 $x$ に対して， $l_{ij} &lt; x_{ij} &lt; u_{ij}$ を満たす辺を free arc，$x_{ij} = l_{ij}$ か $x_{ij} = u_{ij}$ を満たす辺を restricted arc と呼びます．
解 $x$ とそれに関連する全域木が以下の条件を満たすとき，spanning tree solution と呼びます．特に，$x$ が 最適解であるとき最適 spanning tree solution と呼びます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$x$ が実行可能解である&lt;/li&gt;
&lt;li&gt;全域木に含まれない辺（non-tree arc）がすべて restricted arc である&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;具体例を示します．簡単のため，辺容量の下限はすべて 0 としコストは省略します．$b(0) = 2$，$b(3) = -2$ とします．&lt;br&gt;
下の図のグラフでは辺 (0, 1)，(2, 3) が free arc，辺 (0, 2)，(1, 2)，(1, 3) が restricted arc です．&lt;br&gt;
解 $x$ は流量保存則と容量制約を満たすため実行可能解です．全域木として，青色の辺 (0, 1)，(0, 2)，(2, 3) を選ぶ&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;と，non-tree arc は (1, 2) と (1, 3) となり，すべて restricted arc であるため spanning tree solution となります．&lt;/p&gt;
&lt;img src="images/spanning_tree_solutionの例1.png" width="50%"&gt;
&lt;p&gt;また，全域木として，青色の辺 (0, 1)，(1, 2)，(2, 3) を選んでも spanning tree solution となります．
このように，1 つの実行可能解に複数の spanning tree solution が対応することがあります．&lt;/p&gt;
&lt;img src="images/spanning_tree_solutionの例2.png" width="50%"&gt;
&lt;h2 id="2-spanning-tree-structure-と最適性条件"&gt;2. spanning tree structure と最適性条件
&lt;/h2&gt;&lt;p&gt;spanning tree solution は辺集合を次の 3 つに分割します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;T: 全域木の辺&lt;/li&gt;
&lt;li&gt;L: non-tree arc のうち，flow が下限の辺&lt;/li&gt;
&lt;li&gt;U: non-tree arc のうち，flow が上限の辺&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;この 3 つ組 (T, L, U) を spanning tree structure と呼びます．spanning tree structure は spanning tree solution から一意に構築されます．&lt;/p&gt;
&lt;p&gt;頂点 i のポテンシャルを $\pi(i)$，辺 (i, j) の reduced cost を $c_{ij}^{\pi} = c_{ij} - \pi(i) + \pi(j)$ で表します．spanning tree structure が次の条件を満たすとき，spanning tree structure に対応する spanning tree solution は最適 spanning solution となります．このような，spanning tree structure を最適 spanning tree structure と呼びます．&lt;/p&gt;
$$
\begin{aligned}
c^{\pi}_{ij} = 0 &amp;&amp; \forall (i, j) \in T \\
c^{\pi}_{ij} \ge 0 &amp;&amp; \forall (i, j) \in L \\
c^{\pi}_{ij} \le 0 &amp;&amp; \forall (i, j) \in U \\
\end{aligned}
$$&lt;p&gt;全域木の根のポテンシャルを 0 と固定すると $T$ に属する辺 (i, j) が $c^{\pi}_{ij} = 0$ を満たすように各頂点のポテンシャル $\pi$ を定めることができます．このとき，$-\pi(i)$ は根から頂点 i への木のパスの長さとみなすことができます．
具体例として，下の図の全域木について各頂点のポテンシャルを求めていきます．頂点 0 を根とします．&lt;/p&gt;
&lt;p&gt;頂点 1 のポテンシャルを求めます．
辺 (i, j) の reduced cost は $c_{ij}^{\pi} = c_{ij} - \pi(i) + \pi(j)$ です．全域木の辺の reduced cost は 0，辺 (0, 1) のコストは 1，頂点 0 のポテンシャルは 0 であることから，$0 = 1 - 0 + \pi(1)$ となり，$\pi(1) = -1$と求められます．&lt;/p&gt;
&lt;p&gt;頂点 2 のポテンシャルを求めます．
辺 (2, 1) のコストは 5 ，頂点 1 のポテンシャルは -1 なので，$0 = 5 - \pi(2) + (-1)$ となり，$\pi(2) = 4$ と求められます．&lt;/p&gt;
&lt;p&gt;同様の計算を行うことで，全頂点のポテンシャルを計算することができます．&lt;/p&gt;
&lt;img src="images/ポテンシャルの計算.png" width="50%"&gt;
&lt;p&gt;全頂点のポテンシャルを求めると，$L$ と $U$ に属する辺の reduced cost を計算することができます．すべての辺が最適性条件を満たすならば，最適 spanning tree structure と判定できます．&lt;/p&gt;
&lt;h2 id="3-network-simplex-法のアルゴリズムの流れ"&gt;3. Network Simplex 法のアルゴリズムの流れ
&lt;/h2&gt;&lt;p&gt;spanning tree structure が与えられたとき，全域木の reduced cost が 0 となるように各頂点のポテンシャルを計算し，各辺の reduced cost を求めることで最適 spanning structure かどうか判定することができました．
最適 spanning tree structure でない場合， $L$ に属する $c_{ij}^{\pi} \lt 0$ である辺か，$U$ に属する $c_{ij}^{\pi} \gt 0$ である辺が 1 つ以上存在することになります．
これらの辺を $T$ に追加したときを考えます．&lt;/p&gt;
&lt;h3 id="に属する--である辺を--に追加"&gt;$L$ に属する $c^{\pi}_{ij} \lt 0$ である辺を $T$ に追加
&lt;/h3&gt;&lt;p&gt;$L$ に属する $c_{ij}^{\pi} \lt 0$ である辺 (i, j) を $T$ に追加したとします．&lt;br&gt;
このとき，根から i，i から j，j から根をたどるパスの flow を 1 増加すると，目的関数値は $c^{\pi}_{ij}$ 増加します．&lt;/p&gt;
&lt;p&gt;具体例を見てみます．下の図の全域木にコスト -8 の辺 (2, 4) を追加したとします．この辺の reduced cost は $-8 - 4 + (-3) = -15$ です．&lt;br&gt;
辺 (0, 1)，(2, 1)，(2, 4)，(3, 4)，(3, 0) の順に flow を 1 単位流すと，全体のコストの合計は，1 + (-5) + (-8) + (-5) + 2 = -15 となり，目的関数値が 15 減少する（-15 増加する）ことがわかります&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;．&lt;/p&gt;
&lt;img src="images/全域木にLの辺を追加.png" width="50%"&gt;
&lt;h3 id="に属する--である辺を--に追加-1"&gt;$U$ に属する $c^{\pi}_{ij} \gt 0$ である辺を $T$ に追加
&lt;/h3&gt;&lt;p&gt;$U$ に属する $c_{ij}^{\pi} \gt 0$ である辺 (i, j) を $T$ に追加したとします．&lt;br&gt;
このとき，根から j， j から i，i から根をたどるパスの flow を 1 増加すると，目的関数値は $c^{\pi}_{ij}$ 減少します．&lt;/p&gt;
&lt;p&gt;下の図の全域木にコスト -5 の辺 (6, 4) を追加したとします．この辺の reduced cost は $(-5) - (-11) + (-3) = 3$ です．&lt;br&gt;
辺 (3, 0)，(3, 4)，(6, 4)，(5, 6)，(3, 5)，(3, 0) の順に flow を 1 単位流すと，全体のコストの合計は，-2 + 5 + (-(-5)) + (-7) + (-6) + 2 = -3 となり，目的関数値が 3 減少することがわかります．&lt;br&gt;
また，辺 (0, 3) に対し，頂点 0 から 頂点 3 に flow を流し，頂点 3 から頂点 0 に flow を流すと flow は打ち消し合うため，追加した辺によって生じる閉路のみを考慮すればいいこともわかります．&lt;/p&gt;
&lt;img src="images/全域木にUの辺を追加.png" width="50%"&gt;
&lt;p&gt;以上のことから，spanning tree structure が最適でないとき，最適性条件に違反する辺を全域木に追加したことによって生じる閉路の flow を更新することで目的関数値を減少できることがわかりました．&lt;br&gt;
閉路の flow を限界まで増加させると，1 本以上の辺の flow が下限容量か上限容量に達するため，その辺を取り除くことによって新しい spanning tree solution を生成することができます．&lt;br&gt;
primal network simplex 法は これらの処理を最適性条件を満たすまで繰り返すことで最適解を求めます．&lt;/p&gt;
&lt;p&gt;primal network simplex 法の流れは以下のようになります&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;初期 spanning tree structure を構築する&lt;/li&gt;
&lt;li&gt;spanning tree structure が最適性条件を満たさない間，以下を繰り返す
&lt;ul&gt;
&lt;li&gt;最適性条件に違反する辺を $U$ か $L$ から選び，全域木に追加する&lt;/li&gt;
&lt;li&gt;閉路の flow を更新する&lt;/li&gt;
&lt;li&gt;flow が下限容量か上限容量に達した辺を閉路から 1 つ取り除き新しく全域木を作成する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;次節からアルゴリズムの各段階の詳細について説明していきます．&lt;/p&gt;
&lt;h2 id="4-初期-spanning-tree-structre-の構築"&gt;4. 初期 spanning tree structre の構築
&lt;/h2&gt;&lt;p&gt;初期 spanning tree structre (T, L, U) を構築します．&lt;br&gt;
まず，人工頂点 $s$ を作り，$s$ と既存の各頂点 $u$ の間に以下のように辺をはります．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$b(u) \ge 0$ の場合，流量 $b(u)$ の辺 $(u, s)$ を加える&lt;/li&gt;
&lt;li&gt;$b(u) \lt 0$ の場合，流量 $-b(u)$ の辺 $(s, u)$ を加える&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;いずれの人工辺も容量とコストは十分大きい値とします．人工辺は $T$ に，もとからある辺は $L$ に，$U$ は空とします.&lt;br&gt;
このように作られた spanning tree structure は実行可能解です．今後はこの拡張された network 上で問題を解いていきます．人工辺のコストは十分大きいため最適解が得られたとき人工辺に flow は流れていません．&lt;/p&gt;
&lt;p&gt;例として下のグラフの初期 spanning tree structure を構築します．&lt;br&gt;
$b(0) = 2$，$b(3) = -2$，他の頂点の需要/供給は 0 とします．また，すべての辺の下限容量は 0 とします&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;．&lt;/p&gt;
&lt;img src="images/初期解の問題例.png" width="50%"&gt;
&lt;p&gt;まず，人工頂点として，$s$ を追加します．&lt;br&gt;
$b(u) \ge 0$ である頂点 0, 1, 2 から s に向けて辺を追加します．$b(0) = 2$ であるため，辺 (0, s)の flow は 2 とします．&lt;br&gt;
s から $b(u) \lt 0$ である頂点 3 に向けて辺を追加します．$b(3) = -2$ であるため，辺 (s, 3)の flow は 2 とします．&lt;/p&gt;
&lt;img src="images/初期解の構築.png" width="50%"&gt;
&lt;p&gt;初期 spanning tree structure は以下のようになります．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$T$ に属する辺：(0, s)，(1, s)，(2, s)，(s, 3)&lt;/li&gt;
&lt;li&gt;$L$ に属する辺：(0, 1)，(0, 2)，(1, 2)，(1, 3)，(2, 3)&lt;/li&gt;
&lt;li&gt;$U$ に属する辺：なし&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="5-entring-arc-の選択"&gt;5. entring arc の選択
&lt;/h2&gt;&lt;p&gt;$T$ に追加する辺（entring arc）を $U$ か $L$ から選びます．&lt;br&gt;
このとき，以下のような最適性条件を満たさない辺（eligible arc）を選びます．また，$|c^{\pi}_{ij}|$ を violation と呼びます．&lt;/p&gt;
$$
\begin{aligned}
c^{\pi}_{ij} \lt 0 &amp;&amp; \forall (i, j) \in L \\
c^{\pi}_{ij} \gt 0 &amp;&amp; \forall (i, j) \in U
\end{aligned}
$$&lt;p&gt;代表的な辺の選択方法は以下の 3 つです．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Best eligible arc pivot rule(Dantzig&amp;rsquo;s pivot rule)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;violation の最も大きい eligible arc を entring arc とする&lt;/li&gt;
&lt;li&gt;1 flow 単位の改善が最も大きいため，イテレーションの回数は少なくなる&lt;/li&gt;
&lt;li&gt;すべての non-tree arc を調べる必要があるため，1 回のイテレーションのコストが大きい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;First eligible arc pivot rule&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最初に見つけた eligible arc を entring arc とする．次のイテレーションでは，前回選択した辺の次から探索を開始する．最後の辺まで探索をしたら先頭に戻る&lt;/li&gt;
&lt;li&gt;1 回のイテレーションのコストが小さい&lt;/li&gt;
&lt;li&gt;1 flow 単位の改善が小さくなるので，イテレーションの回数が多くなる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Block search pivot rule&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;辺をブロックに分割し，ブロックの中で violation の最も大きい eligible arc を entring arc とする．ブロック内で見つからなかった場合，次のブロックを探索する&lt;/li&gt;
&lt;li&gt;すべての辺を同じブロックにしたとき，Best eligible arc pivot rule と同じ挙動になる&lt;/li&gt;
&lt;li&gt;すべての辺を違うブロックにしたとき，First eligible arc pivot rule と同じ挙動になる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="6-flow-の更新"&gt;6. flow の更新
&lt;/h2&gt;&lt;p&gt;全域木に辺を追加すると閉路 $W$ がちょうど 1 つできます．この閉路の flow を 1 単位増加するごとに，MCFP の目的関数値は $|c^{\pi}_{ij}|$ 減少するため，$W$ の flow を容量制約を満たす限界まで増加します．&lt;br&gt;
閉路 $W$ の向きを次のように定めます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$(k, l) \in L$ のとき，辺 (k, l) と同じ方向&lt;/li&gt;
&lt;li&gt;$(k, l) \in U$ のとき，辺 (k, l) と逆方向&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;閉路 $W$ の順辺の集合を $\bar W$，逆辺の集合を $\underbar W$ で表したとき，$W$ の各辺の flow の増加できる量は以下のようになります．&lt;/p&gt;
$$
\delta_{ij} = \left\{
\begin{array}{ll}
u_{ij} - x_{ij} &amp; (i, j) \in \bar{W}\\
x_{ij} - l_{ij} &amp; (i, j) \in \underbar{W}
\end{array}
\right.
$$&lt;p&gt;$\delta = min \lbrace \delta_{ij} : (i, j) \in W \rbrace$ とし，$W$ の各辺の flow を以下のように更新します．&lt;/p&gt;
$$
x_{ij} = \left\{
\begin{array}{ll}
x_{ij} + \delta &amp; (i, j) \in \bar{W}\\
x_{ij} - \delta &amp; (i, j) \in \underbar{W}
\end{array}
\right.
$$&lt;p&gt;具体例を見ます．すべての辺の下限は 0 とします．&lt;br&gt;
$U$ に属する辺 (6, 4) を $T$ に追加すると，辺 (6, 4)，(5, 6)，(3, 5)，(3, 4) からなる閉路ができます．&lt;br&gt;
辺 (6, 4) は $U$ に属するので，(6, 4) と逆方向である反時計回りを $W$ の向きとします．$\bar W$ に属する辺は，(3, 4)，$\underbar W$ に属する辺は，(6, 4)，(5, 6)，(3, 5) です．&lt;br&gt;
各辺の $\delta_{ij}$ と $\delta$ は以下の通りです．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\delta_{64} = 6 - 0 = 6$&lt;/li&gt;
&lt;li&gt;$\delta_{56} = 2 - 0 = 2$&lt;/li&gt;
&lt;li&gt;$\delta_{35} = 4 - 0 = 4$&lt;/li&gt;
&lt;li&gt;$\delta_{34} = 3 - 1 = 2$&lt;/li&gt;
&lt;li&gt;$\delta = min \lbrace 6, 2, 4, 2 \rbrace = 2$&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/閉路のflowの更新.png" width="50%"&gt;
&lt;p&gt;閉路 $W$ の flow を 2 増加すると以下のようになります．&lt;/p&gt;
&lt;img src="images/閉路のflowの更新結果.png" width="50%"&gt;
&lt;p&gt;別の例をみます．
辺 (3, 4) の flow が 3 のとき，各辺の $\delta_{ij}$は以下のようになります．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\delta_{64} = 6 - 0 = 6$&lt;/li&gt;
&lt;li&gt;$\delta_{56} = 2 - 0 = 2$&lt;/li&gt;
&lt;li&gt;$\delta_{35} = 4 - 0 = 4$&lt;/li&gt;
&lt;li&gt;$\delta_{34} = 3 - 3 = 0$&lt;/li&gt;
&lt;li&gt;$\delta = min \lbrace 6, 2, 4, 0 \rbrace = 0$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このように全域木に $x_{ij} = l_{ij}$ や $x_{ij} = u_{ij}$ の辺があると flow が更新できないことがあります．&lt;/p&gt;
&lt;img src="images/閉路のflowを更新できない例.png" width="50%"&gt;
&lt;h2 id="7-leaving-arc-の選択"&gt;7. leaving arc の選択
&lt;/h2&gt;&lt;p&gt;閉路の flow を限界まで増加したとき 1 本以上の辺が $\delta = \delta_{ij}$ となります．この辺を blocking arc と呼びます．&lt;br&gt;
blocking arc を取り除く辺（leaving arc）として選びます（複数ある場合は任意の辺を選びます）．&lt;br&gt;
辺 (i, j) が $x_{ij}$ = $l_{ij}$ になったときは $L$ に，$x_{ij} = u_{ij}$ になったときは $U$ に入ります．&lt;/p&gt;
&lt;p&gt;閉路 $W$ の flow を更新した結果，辺 (5, 6) の flow が下限容量に，辺 (3, 4) の flow が上限容量になった場合を考えます．&lt;/p&gt;
&lt;img src="images/閉路のflowの更新結果.png" width="50%"&gt;
&lt;p&gt;辺 (5, 6) と辺 (3, 4) のどちらかを取り除くことができます．辺 (5, 6) を取り除き $L$ に追加すると下の全域木 $T$ が得られます．&lt;/p&gt;
&lt;img src="images/閉路の辺の削除.png" width="50%"&gt;
&lt;h2 id="8-ポテンシャルの更新"&gt;8. ポテンシャルの更新
&lt;/h2&gt;&lt;p&gt;辺 (p, q) を削除したとき，木は 2 つの部分木に分割されます．根がある方の部分木を $T_1$，ない方の部分木を $T_2$ とします．&lt;br&gt;
木の根のポテンシャルを 0 に固定し， 辺の reduced cost が 0 になるようにポテンシャルを算出していたことを考えると，$T_1$ に含まれる頂点のポテンシャルは変化せず，$T_2$ に含まれる頂点のポテンシャルのみ変化することがわかります．&lt;/p&gt;
&lt;p&gt;全域木に辺 (k, l) が追加され，頂点 k が $T_1$ に，頂点 l が $T_2$ に含まれる場合を考えます．&lt;br&gt;
$T_2$ は頂点 q を根とする部分木から頂点 l を根とする部分木に変化するため，$T_2$ に属する頂点のポテンシャルを更新する必要があります．&lt;br&gt;
木のすべての頂点のポテンシャルに定数を加算しても reduced cost は保たれるため，新しい $\pi(l)$ と現在の $\pi(l)$ の差分 $d$ が求められれば，$T_2$ に属するすべての頂点に $d$ を加算することでポテンシャルを正しい値に更新できます．&lt;br&gt;
頂点 k のポテンシャルは変化しないことから，頂点 l の新しいポテンシャル $\pi^{\prime}(l)$ は $0 - c_{kl} + \pi(k)$ となります．&lt;br&gt;
よって，頂点 l の新しいポテンシャルとの現在のポテンシャルの差は $\pi^{\prime}(l) - \pi(l) = 0 - c_{kl} + \pi(k) - \pi(l) = -(c_{kl} - \pi(k) + \pi(l))$ となり，これは $-c_{kl}^{\pi}$ です．&lt;br&gt;
以上のことから，$T_2$ に属するすべての頂点に $-c_{kl}^{\pi}$ を加算することでポテンシャルを正しい値に更新できることがわかりました．&lt;br&gt;
頂点 l が $T_1$ に，頂点 k が $T_2$ に含まれる場合も同様の議論により，$c_{kl}^{\pi}$ 増加することが示せます．&lt;/p&gt;
&lt;p&gt;まとめると，辺 (k, l)を追加したとき $T_2$ に含まれる頂点のポテンシャルは以下のように更新されます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;頂点 k が $T_1$ に，頂点 l が $T_2$ に含まれる場合
&lt;ul&gt;
&lt;li&gt;$T_2$ に含まれる頂点のポテンシャルは $-c^{\pi}_{kl}$ 増加&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;頂点 l が $T_1$ に，頂点 k が $T_2$ に含まれる場合
&lt;ul&gt;
&lt;li&gt;$T_2$ に含まれる頂点のポテンシャルは $c^{\pi}_{kl}$ 増加&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="images/ポテンシャルの更新.png" width="75%"&gt;
&lt;h2 id="9-strongly-feasible-spanning-tree"&gt;9. Strongly Feasible Spanning Tree
&lt;/h2&gt;&lt;p&gt;primal network simplex 法が有限回で終了するのかを考えます．&lt;br&gt;
アルゴリズムの各イテレーションでは，全域木に辺を追加するこことで閉路を作り，この閉路の flow を更新することで目的関数値を減少させます．&lt;br&gt;
目的関数値は flow 1 単位あたり $|c^{\pi}_{ij}|$ 減少するため，常に正の量の flow を流せるならアルゴリズムは有限回で終了します．&lt;br&gt;
しかし，節 6 の最後の例のように閉路に restricted arc があると flow が増加できないイテレーションが発生することがあります．このイテレーションを degenerate iteration といいます．&lt;br&gt;
実は primal network simplex 法は entring arc と leaving arc を任意に選ぶと degenerate iteration が無限に発生しアルゴリズムが有限回で終了しないことがあります．&lt;/p&gt;
&lt;p&gt;そこで，strongly feasible spanning tree という概念を導入します．&lt;br&gt;
常に strongly feasible spanning tree を維持することによって，アルゴリズムが有限回で終了することが保証できます．&lt;/p&gt;
&lt;h3 id="strongly-feasible-spanning-tree"&gt;strongly feasible spanning tree
&lt;/h3&gt;&lt;p&gt;次の条件を満たす spanning tree を strongly feasible spanning tree と呼びます．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;任意の頂点から正の量の flow を容量制約に違反することなく木に沿って根に送ることができる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下の図は strongly feasible spanning tree の例です．&lt;br&gt;
すべての頂点から頂点 0 に向かって 1 以上の flow を送ることができます．&lt;br&gt;
strongly feasible spanning tree は flow が下限の辺のは根に向いていて，flow が上限の辺は根と反対を向いている全域木とみなすこともできます．&lt;/p&gt;
&lt;img src="images/strongly_feasible_spanning_treeの例.png" width="50%"&gt;
&lt;p&gt;下の図は strongly feasible spanning tree ではない例です．&lt;br&gt;
辺 (2, 1) の flow は上限容量であるため，頂点 2 から根に flow を送ることはできません．また，辺 (3, 4) の flow は下限容量であるため，頂点 4 から根に flow を送ることはできません．&lt;/p&gt;
&lt;img src="images/strongly_feasible_spanning_treeではない例.png" width="50%"&gt;
&lt;p&gt;節 4 の「初期 spanning tree structure の構築」は strongly feasible spanning tree を構築します．次の節で leaving arc をどのように選べば strongly feasible spanning tree を維持できるのか見ていきます．&lt;/p&gt;
&lt;h2 id="10-strongly-feasible-spanning-tree-を保つ-leaving-arc-の選び方"&gt;10. Strongly Feasible Spanning Tree を保つ leaving arc の選び方
&lt;/h2&gt;&lt;p&gt;辺 (k, l) を entring arc とします．頂点 k と l の最小共通祖先を頂点 w とします．&lt;br&gt;
このとき閉路 $W$ に沿って，頂点 w から開始して最後に見つけた blocking arc を leaving arc とすると，spanning tree は strongly feasible を維持できます．&lt;/p&gt;
&lt;p&gt;具体例をみます．&lt;br&gt;
$L$ に属する辺 (k, l) が追加され閉路 $W$ が生成されたとします．閉路の向きは辺 (k, l) と同じ向きです．&lt;br&gt;
この閉路には flow を流すことができず，辺 (w, 1) と辺 (p, q) が blocking arc になります．&lt;br&gt;
頂点 w から閉路の向きに沿って探索し，最後に見つかる blocking arc は辺 (p, q) であるため，この辺を leaving arc とします．&lt;/p&gt;
&lt;img src="images/strongly_feasible_spanning_treeを維持するようなleaving_arcの選び方.png" width="30%"&gt;
&lt;p&gt;strongly feasible spanning tree から上記の方法で leaving arc を選んだとき，strongly feasible spanning tree が維持されることを示します．pivot 操作の直前は strongly feasible spanning tree であるという前提を利用します．&lt;/p&gt;
&lt;p&gt;頂点 w から頂点 q のパスを $W_1$，頂点 p から頂点 w のパスを $W_2$ とします．&lt;br&gt;
「$W_1$」，「$W_2$」，「閉路以外の頂点」の 3 つについて，「任意の頂点から正の量の flow を容量制約に違反することなく木に沿って根に送ることができる」という条件を満たすか確認します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$W_1$ 内の頂点&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直前が non-degenerate pivot&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt; の場合
&lt;ul&gt;
&lt;li&gt;$\delta \gt 0$ であるため，頂点 w から$W_1$ 内の頂点に flow が送られている．$W_1$ の各頂点からは頂点 w まで $\delta$ の flow を押し戻すことができるため条件を満たす&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;直前が degenerate pivot&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt; の場合
&lt;ul&gt;
&lt;li&gt;前提から，pivot の直前では頂点 l から頂点 w のパスで flow を送れていたため，このパス内に blocking arc は存在しない．よって $W_1$ は頂点 w と頂点 k の間にある&lt;/li&gt;
&lt;li&gt;$\delta = 0$ であり，頂点 w から頂点 k のどの辺の flow にも変化はないため条件を満たす&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$W_2$ 内の頂点&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;leaving arc の選び方を考えると，$W_2$ 内に blocking arc はないため条件を満たす&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$W$ 以外の頂点&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;頂点 u から根へのパスに閉路 $W$ が含まれないとき
&lt;ul&gt;
&lt;li&gt;前提から，閉路以外の flow に変化はないため，条件を満たす&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;頂点 u から根へのパスに閉路 $W$ が含まれるとき
&lt;ul&gt;
&lt;li&gt;u から閉路までのパスは，flow に変化がないため条件を満たす．閉路に到達したとき閉路から根まで条件を満たすので全体として条件を満たす&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上のことから，leaving arc に $W$ に沿って最後に見つけた blocking arc を選ぶことで，常に strongly feasible spanning tree を維持できることがわかりました．&lt;/p&gt;
&lt;h2 id="11-アルゴリズムが有限回で終了することの証明"&gt;11. アルゴリズムが有限回で終了することの証明
&lt;/h2&gt;&lt;p&gt;2 つの non-degenerate pivot の間の連続する degenerate pivot が有限回であることを示します．&lt;/p&gt;
&lt;p&gt;degenerate pivot が発生したとき，ノードのポテンシャルが単調減少することを示します．$n$ を頂点の数，$C$ をコストの絶対値の最大値としたとき，ノードのポテンシャルの下界は $-nC$ であるため連続する degenerate pivot は有限回で終了します．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;entring arc (k, l) が $L$ に属していた場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;辺 (k, l) は $L$ に属し，最適性条件に違反するため，reduced cost は $c^{\pi}_{kl} \lt 0$ です．&lt;/li&gt;
&lt;li&gt;全域木は常に strongly feasible spanning tree を維持していることを考えると，degenerate pivot の場合は頂点 l から頂点 w の間に blocking arc は存在しないため，新しく作成される木は頂点 l に 頂点 k がぶら下がる形になります．&lt;/li&gt;
&lt;li&gt;頂点 k を根とする部分木のポテンシャルは $c^{\pi}_{kl} \lt 0$ 増加するため，ノードのポテンシャルは単調減少します&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;entring arc (k, l) が $U$ に属していた場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;辺 (k, l) は $U$ に属し，最適性条件に違反するため，reduced cost は $c^{\pi}_{kl} \gt 0$ です．&lt;/li&gt;
&lt;li&gt;新しく作成される木は頂点 k に 頂点 l がぶら下がる形になります．&lt;/li&gt;
&lt;li&gt;頂点 l を根とする部分木のポテンシャルは $c^{\pi}_{kl} \gt 0$ 減少するため，ノードのポテンシャルは単調減少します&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上のことから 2 つの non-degenerate pivot の間の連続する degenerate pivot が有限回であることがわかりました．
non-degenerate pivot は目的関数値を厳密に減少させるため，アルゴリズムは有限回で終了します．&lt;/p&gt;
&lt;h2 id="補足-1-最適-spanning-tree-solution-が必ず存在することについて"&gt;補足 1. 最適 spanning tree solution が必ず存在することについて
&lt;/h2&gt;&lt;h3 id="cycle-free-solution"&gt;cycle free solution
&lt;/h3&gt;&lt;p&gt;free arc のみからなる閉路を持たないような実行可能解 $x$ を cycle free solution といいます．&lt;/p&gt;
&lt;p&gt;下の図は cycle free solution の例です．辺の上に (流量，コスト) を示し，下限容量は 0，上限容量は無限とします．&lt;br&gt;
青色の辺 (0, 1)，(1, 3)，(3, 4) が free arc です．free arc のみからなる閉路がないため cycle free solution です．この解の目的関数値は $(2 \times 0) + (2 \times 1) + (2 \times 0) = 2$ です．&lt;/p&gt;
&lt;img src="images/cycle_free_solutionの例.png" width="50%"&gt;
&lt;p&gt;下の図は cycle free solution ではない例です．&lt;br&gt;
青色の辺 (0, 1)，(1, 2)，(1, 3)，(2, 4)，(3, 4) が free arc です．free arc のみからなる閉路があるため cycle free solution ではありません．この解の目的関数値は $(2 \times 0) + (1 \times 3) + (1 \times 1) + (1 \times -1) + (1 \times 0) = 3$ です．&lt;/p&gt;
&lt;img src="images/cycle_free_solutionではない例.png" width="50%"&gt;
&lt;p&gt;cycle free solution でない解が与えられたとき，閉路の flow を操作することで，目的関数値が大きくならないように cycle free solution にすることができます．&lt;br&gt;
この解の場合，時計回りに flow を 1 増加すると，辺 (2, 4)，(1, 2) の flow が 1 減り，辺(1, 3)，(3, 4) の flow が 1 増えます．結果，この解の目的関数値は $(2 \times 0) + (0 \times 3) + (2 \times 1) + (0 \times -1) + (2 \times 0) = 2$ と 1 小さくなり，さらに cycle free solution になりました．&lt;/p&gt;
&lt;img src="images/cycle_free_solutionに変形.png" width="50%"&gt;
&lt;p&gt;このように，cycle free でない解は閉路の flow を操作することで目的関数値が大きくならないように cycle free solution にできるため，MCFP に最適解があるとき，常に同じ目的関数値である cycle free solution を持つことがわかります．&lt;/p&gt;
&lt;h3 id="cycle-free-solution-から-spanning-tree-solution-を求める"&gt;cycle free solution から spanning tree solution を求める
&lt;/h3&gt;&lt;p&gt;cycle free solution は辺を適切に選ぶことで spanning tree solution を求めるとができます．&lt;br&gt;
下の図では，青色の辺(0, 1)，(1, 2)，(1, 3)，(3, 4) を全域木として選んでいます．&lt;/p&gt;
&lt;img src="images/cycle_free_solutionをspanning_tree_solutionに.png" width="50%"&gt;
&lt;p&gt;以上のことから，MCFP に最適解があるとき，常に同じ目的関数値である最適 spanning tree solution を持つことがわかりました．&lt;/p&gt;
&lt;h2 id="補足-2-spanning-tree-structure-の最適性条件"&gt;補足 2. Spanning Tree Structure の最適性条件
&lt;/h2&gt;&lt;p&gt;spanning tree structure が次の条件を満たすとき，spanning tree structure に対応する spanning tree solution は最適 spanning solution となることを示します．&lt;/p&gt;
$$
\begin{aligned}
c^{\pi}_{ij} = 0 &amp;&amp; \forall (i, j) \in T \\
c^{\pi}_{ij} \ge 0 &amp;&amp; \forall (i, j) \in L \\
c^{\pi}_{ij} \le 0 &amp;&amp; \forall (i, j) \in U \\
\end{aligned}
$$&lt;p&gt;まず，$\sum_{(i, j) \in A} c_{ij} x_{ij}$ を最小化することは $\sum_{(i, j) \in A} c_{ij}^{\pi} x_{ij}$ を最小化することと等しいことを示します．&lt;/p&gt;
&lt;p&gt;$z(\pi) = \sum_{(i, j) \in A} c_{ij}^{\pi} x_{ij}$ とします．$c_{ij}^{\pi} = c_{ij} - \pi(i) + \pi(j)$ なので，$z(0) = \sum_{(i, j) \in A} c_{ij} x_{ij}$ です．&lt;br&gt;
頂点 k のポテンシャルを $0$ から $\pi(k)$ まで増加したとします．&lt;br&gt;
$c_{ij}^{\pi} = c_{ij} - \pi(i) + \pi(j)$ なので，reduced cost は頂点 k から流出する flow 1 単位あたり $\pi(k)$ 減少し，頂点 k に流入する flow 1 単位あたり $\pi(k)$ 増加します．よって，全体の reduced cost は $ - \pi(k) \times k$ からの流出量 + $\pi(k) \times k$ への流入量だけ変化します．&lt;/p&gt;
&lt;p&gt;MCFP の制約条件から，各頂点 i の流出量と流入量の関係は $\sum_{j:(i, j) \in A} x_{ij} - \sum_{j:(j,i) \in A} x_{ji} = b_i$ です．&lt;br&gt;
よって，頂点 k のポテンシャルを $\pi(k)$ 増加すると，目的関数値は $\pi(k)b(k)$ 減少することになります．&lt;br&gt;
すべての頂点に同様のことがいえるので，$z(0) - z(\pi) = \sum_{i \in N} \pi(i)b(i) = \pi b$ となります．&lt;br&gt;
$\pi b$ は定数のため，$z(\pi)$ を最小化する flow は $z(0)$ を最小化することがわかりました．&lt;/p&gt;
&lt;p&gt;次に，$x^{\ast}$ を上の最適性条件を満たす (T, L, U) に対応する解としたとき，これが最適解であることを示します．&lt;br&gt;
最適性条件を満たすポテンシャルを $\pi$ としたとき，$\sum_{(i, j) \in A} c_{ij}^{\pi} x_{ij}$ の最小化を考えます．&lt;br&gt;
$\sum_{(i, j) \in A} c_{ij}^{\pi} x_{ij}$ を最小化することは $\sum_{(i, j) \in L} c_{ij}^{\pi} x_{ij} - \sum_{(i, j) \in U} |c_{ij}^{\pi}| x_{ij}$ を最小化すること等しいです．&lt;/p&gt;
&lt;p&gt;$\forall (i, j) \in L$ に対して $x_{ij} \ge x_{ij}^{\ast} = l_{ij}$ であり，$\forall (i, j) \in U$ に対して $x_{ij} \le x_{ij}^{\ast} = u_{ij}$ であるため，$x^{\ast}$ の目的関数値は $x$ の目的関数値以下となります．&lt;br&gt;
以上のことから，最適性条件を満たす spanning tree structure は最適解となることがわかりました．&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.amazon.co.jp/dp/1292042702" target="_blank" rel="noopener"
&gt;Network Flows: Pearson New International Edition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://homes.di.unimi.it/righini/Didattica/OttimizzazioneCombinatoria/MaterialeOC/9b%20-%20NetworkSimplex.pdf" target="_blank" rel="noopener"
&gt;The network simplex algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://coral.ise.lehigh.edu/~ted/teaching/ie411/" target="_blank" rel="noopener"
&gt;IE 411: Graphs and Network Flows (Python)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;正確には，実行可能領域に下界が存在するならば最適 spanning tree solution が少なくとも 1 つ存在します．&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;全域木の辺として restricted arc を選ぶこともできます&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;辺 (i, j) に対し頂点 j から頂点 i に flow を流すと，辺 (i, j) の flow を減らすことになります．例えば，辺 (2, 1) に対して頂点 1 から頂点 2 に flow を流すと，辺 (2, 1) の flow は 1 減り，コストは 5 下がります．&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;辺の lower が 0 でない場合，先に lower 分の flow を流しておきます．&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;$\delta \gt 0$ である pivot&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;$\delta = 0$ である pivot&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Green Hackenbush の木のグランディ数</title><link>https://miti-7.github.io/post/green-hackenbush-tree-grundy/</link><pubDate>Tue, 10 Sep 2024 00:00:00 +0900</pubDate><guid>https://miti-7.github.io/post/green-hackenbush-tree-grundy/</guid><description>&lt;img src="https://miti-7.github.io/post/green-hackenbush-tree-grundy/images/%E3%82%B3%E3%83%AD%E3%83%B3%E5%8E%9F%E7%90%86%E3%81%AE%E4%BE%8B.png" alt="Featured image of post Green Hackenbush の木のグランディ数" /&gt;&lt;h2 id="1-はじめに"&gt;1. はじめに
&lt;/h2&gt;&lt;p&gt;Green Hackenbush は以下のルールをもつ有限型不偏ゲームです．&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;点線で表された地面，点，点と点を結ぶ有限個の辺からなる図形がある&lt;/li&gt;
&lt;li&gt;どの図形のどの部分も辺をたどると地面につながる&lt;/li&gt;
&lt;li&gt;2 人のプレーヤーは交互に図形から 1 つの辺を選んで取り除く．選んだ辺を取り除くことで地面とつながらなくなってしまう部分は辺と同時に取り除かれる&lt;/li&gt;
&lt;li&gt;最後の辺をとったプレーヤーの勝ち&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Green Hackenbush は有限型不偏ゲームなので各図形のグランディ数を求めることができます．今回は木と呼ばれる図形のグランディ数を求めていきます．&lt;br&gt;
節 2 と 節 3 では Green Hackenbush で一般に適用できる性質を確認します．節 4 と 節 5 ではこの性質を利用し具体的な図形のグランディ数を求める方法を示します．&lt;br&gt;
最後に節 6 で Green Hackenbush の木のグランディ数を求める問題を紹介します．&lt;/p&gt;
&lt;h2 id="2-地面の点の移動"&gt;2. 地面の点の移動
&lt;/h2&gt;&lt;p&gt;地面上にある点を移動してもゲームのグランディ数は変わらないので，自由に移動させることができます．&lt;/p&gt;
&lt;img src="images/地面の点の移動.png" width="50%"&gt;
&lt;h2 id="3-コロン原理colon-principle"&gt;3. コロン原理(Colon Principle)
&lt;/h2&gt;&lt;p&gt;コロン原理&lt;br&gt;
図形 A のグランディ数を $g(A)$ とする．地面についている図形 $G$ と宙に浮いている図形 $H$ が 1 つの点 $a$ のみを共有してできる図形を $H \cup_a G$ と表す．このとき，宙に浮いている図形 $H$，$K$ が $g(H) = g(K)$ を満たすならば，$g(H \cup_a G) = g(K \cup_a G)$ となる．&lt;/p&gt;
&lt;img src="images/コロン原理.png" width="50%"&gt;
&lt;details&gt;&lt;summary&gt;証明&lt;/summary&gt;
&lt;p&gt;$g(H \cup_a G) = g(K \cup_a G)$ ということは，$g(H \cup_a G) \\ xor \\ g(K \cup_a G) = 0$ なので，$H \cup_a G と K \cup_a G$ の直和ゲームは後手必勝と言い換えることができます．よって，「$g(H) = g(K)$ を満たすならば後手必勝」を示します．
また，$H \cup_a G$ と $K \cup_a G$ は対称なので，$H \cup_a G$ から辺を取り除く場合のみ考えます．&lt;/p&gt;
&lt;p&gt;先手の手は，「1. $G$ から辺を取り除く」，「2. $H$ から辺を取り除く」の 2 通りです．先手の各手について後手の必勝手を考えます．
グランディ数の定義より，グランディ数 g の局面からはグランディ数 g 未満の局面に遷移できることを利用します．&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;先手が $H \cup_a G$ の $G$ から辺を取り除く場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;後手は $K \cup_a G$ の $G$ から同じ辺を取り除けばいい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;先手が $H ∪_a G$ の $H$ から辺を取り除き，$H^\prime $ にした場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$g(H^\prime) &lt; g(H)$ の場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;仮定より $g(H) = g(K)$ なので，$K$ から辺を取り除いて移行できる $K^\prime$ で，$g(K^\prime) = g(H^\prime)$ となるものがある．後手は $K → K^\prime$ となる辺を取り除けばいい．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$g(H^\prime) &gt; g(H)$ の場合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$H^\prime$ から辺を取り除いて移行できる $H^{\prime \prime}$ で， $g(H^{\prime \prime}) = g(H) = g(K)$ となるものがある．後手は $H^\prime → H^{\prime \prime}$ となる辺を取り除けばいい．&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/details&gt;
&lt;p&gt;コロン原理を使うことで，ある 1 つの点のみを共有している宙に浮いている図形は，同じグランディ数を持つより単純な図形に置き換えることができます．&lt;/p&gt;
&lt;img src="images/コロン原理の例.png" width="50%"&gt;
&lt;h2 id="4-棒のグランディ数"&gt;4. 棒のグランディ数
&lt;/h2&gt;&lt;p&gt;まず，1 つの棒のみからなるゲームのグランディ数について考えます．&lt;br&gt;
長さ m の棒からは，長さ m 未満の棒に遷移できるため，長さ m の棒のグランディ数は m となります．&lt;/p&gt;
&lt;img src="images/棒のグランディ数.png" width="50%"&gt;
&lt;p&gt;次に，複数の棒からなるゲームのグランディ数を考えます．&lt;br&gt;
各棒は独立したゲームの局面とみなすことができるので，複数の棒からなるゲームのグランディ数は各棒のグランディ数の xor で求めることができます．&lt;br&gt;
例えば，長さ 1, 1, 2 の棒からなるゲームのグランディ数は $1 \\ xor \\ 1 \\ xor \\ 2 = 2$ となります．&lt;/p&gt;
&lt;img src="images/複数の棒のグランディ数.png" width="50%"&gt;
&lt;p&gt;最後に，地面のある一点から複数の棒が伸びる図形のグランディ数を考えます．&lt;br&gt;
地面の点は自由に移動することができるため，地面のある一点から複数の棒が伸びる図形は，複数の棒からなるゲームに帰着することができます．&lt;br&gt;
よって，地面のある一点から複数の棒が伸びる図形のグランディ数は，各棒の長さの xor で求めることができます．&lt;/p&gt;
&lt;img src="images/地上の点から複数の棒.png" width="75%"&gt;
&lt;h2 id="5-木のグランディ数"&gt;5. 木のグランディ数
&lt;/h2&gt;&lt;p&gt;コロン原理を順次適用していくことによって，木のグランディ数を求めることができます．&lt;br&gt;
地面のある一点から複数の棒が伸びている図形のグランディ数は，各棒の長さの xor で求めることができました．コロン原理により，ある一点から複数の棒が伸びているような木の点は，各棒の長さの xor をとった値の長さの棒に変換することができます．この操作を繰り返すことで木のグランディ数を求めることができます．&lt;/p&gt;
&lt;img src="images/コロン原理_木.png" width="50%"&gt;
&lt;p&gt;以下に例を示します．&lt;br&gt;
点 a からは，長さ 1 の棒と長さ 3 の棒が伸びています．よって，長さ 1 xor 3 = 2 の棒に置き換えることができます．&lt;br&gt;
点 b からは，長さ 1 の棒と長さ 3 の棒が伸びています．よって，長さ 1 xor 3 = 2 の棒に置き換えることができます．&lt;br&gt;
点 c からは，長さ 2 の棒と長さ 3 の棒と長さ 1 の棒が伸びています．よって，長さ 2 xor 3 xor 1 = 0 の棒に置き換えることができます．&lt;br&gt;
以上のことからこの木のグランディ数は 0 と求めることができました．&lt;/p&gt;
&lt;img src="images/木のグランディ数の例.png" width="75%"&gt;
&lt;h2 id="6-agc017-d---game-on-tree"&gt;6. AGC017 D - Game on Tree
&lt;/h2&gt;&lt;p&gt;Green Hackenbush の木のグランディ数を求める問題として，&lt;a class="link" href="https://atcoder.jp/contests/agc017/tasks/agc017_d" target="_blank" rel="noopener"
&gt;D - Game on Tree&lt;/a&gt; があります．&lt;br&gt;
ある頂点のグランディ数は，「自分の子のグランディ数 + 1」 の xor を使って求めことができるので，根から深さ優先探索をすることで木のグランディ数を求めることができます．&lt;br&gt;
&lt;a class="link" href="https://atcoder.jp/contests/agc017/submissions/56666314" target="_blank" rel="noopener"
&gt;提出コード&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.sugakushobo.co.jp/903342_76_mae.html" target="_blank" rel="noopener"
&gt;石取りゲームの数学&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://en.wikipedia.org/wiki/Hackenbush" target="_blank" rel="noopener"
&gt;Hackenbush&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Archives</title><link>https://miti-7.github.io/archives/</link><pubDate>Tue, 28 May 2019 00:00:00 +0000</pubDate><guid>https://miti-7.github.io/archives/</guid><description/></item><item><title>Links</title><link>https://miti-7.github.io/links/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://miti-7.github.io/links/</guid><description/></item><item><title>Search</title><link>https://miti-7.github.io/search/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://miti-7.github.io/search/</guid><description/></item></channel></rss>