diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d082927..de7b7de 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -96,6 +96,11 @@ Markdown 中に `chokudai` のように AtCoder ID を書 色の情報は [_sass/user-colors.scss](https://github.com/kmyk/algorithm-encyclopedia/blob/gh-pages/_sass/user-colors.scss) ファイルに CSS として保存されています。このファイルは [scripts/user-ratings.py](https://github.com/kmyk/algorithm-encyclopedia/blob/gh-pages/scripts/user-ratings.py) によって生成されます。定期的に `$ python3 scripts/user-ratings.py` を実行して色の情報のファイルを更新してください。 +## 画像ファイル + +[`assets/img/`](https://github.com/kmyk/algorithm-encyclopedia/tree/gh-pages/assets/img) に置いてください。 +また、後から画像を修正する必要が発生したときのために、画像の編集方法を [`assets/img/README.md`](https://github.com/kmyk/algorithm-encyclopedia/tree/gh-pages/assets/img/README.md) に書いておいてください。 + ### ローカルでの記事の閲覧 ローカルで記事を閲覧するには、以下のコマンドを順に実行してください。HTTP サーバが建ち から閲覧できます。 @@ -236,6 +241,7 @@ $ python3 scripts/lint.py - リンクを張るときはリンク先の永続性に注意する。特に他人のブログ記事や競プロライブラリへのリンクを貼るときは [Internet Archive](https://archive.org/web/) によるスナップショットを取っておく ([Save Page Now - Wayback Machine](https://web.archive.org/save/))。 - リンクを張るときはリンク先との関係が分かるようにする。例題を紹介するならば簡単な解説を書いておく。記事を紹介するならばなぜ他の記事でなくその記事が選ばれているのか分かるようにしておく。 - ソースコードはそのままコピペして動くものを載せる。ソースコードの妥当性は簡単に検証できるようにしておく。 +- 画像ファイルは後から他の人が修正しやすいような形式を選び、修正方法のドキュメントを残しておく。 ## ライセンスについて diff --git a/_algorithms/dinic.md b/_algorithms/dinic.md index a88530f..b6ac792 100644 --- a/_algorithms/dinic.md +++ b/_algorithms/dinic.md @@ -9,14 +9,14 @@ algorithm: input: > ネットワーク (つまり有向グラフ $G = (V, E)$ および辺容量 $c : E \to \mathbb{R} _ {\ge 0}$ および相異なる頂点 $s, t \in V$) output: > - $s$-$t$ 最大流 (つまり関数 $f : E \to \mathbb{R} _ {\ge 0}$ であって容量制約とフロー保存則を満たすもの) + $s$-$t$ 最大フロー (つまり関数 $f : E \to \mathbb{R} _ {\ge 0}$ であって容量制約とフロー保存則を満たすもの) time_complexity: > 最悪計算量は $O(\lvert V \rvert^2 \lvert E \rvert)$ だが実用的にはかなり速い。ネットワークの構造によっては計算量が落ちることがある。 space_complexity: aliases: [] level: blue description: > - Dinic 法は最大流問題を解くアルゴリズムのひとつ。 + Dinic 法は最大フロー問題を解くアルゴリズムのひとつ。 残余グラフ上において、辺の本数の意味での $s$-$t$ 最短経路 DAG を BFS により構成し、増加パスをこの DAG の上の DFS により探して流せるだけ流す、という一連のステップを繰り返す。 計算量は $O(\lvert V \rvert^2 \lvert E \rvert)$ だが実用的にはかなり速い。 --- @@ -25,7 +25,7 @@ description: > ## 概要 -Dinic 法は最大流問題を解くアルゴリズムのひとつである。 +Dinic 法は[最大フロー問題](/maximum-flow-problem)を解くアルゴリズムのひとつである。 残余グラフ上において、辺の本数の意味での $s$-$t$ 最短経路 DAG を BFS により構成し、増加パスをこの DAG の上の DFS により探して流せるだけ流す、という一連のステップを繰り返す。 最悪計算量は $O(\lvert V \rvert^2 \lvert E \rvert)$ だが実用的にはかなり速い。また、ネットワークの構造を制限すれば最悪計算量が落ちることがある[^time-complexity]。 @@ -38,8 +38,10 @@ Dinic 法は最大流問題を解くアルゴリズムのひとつである。 ## 関連項目 +- [最大フロー問題](/maximum-flow-problem) + - Dinic 法は最大フロー問題を解くアルゴリズムである。 - [Ford-Fulkerson 法](/ford-fulkerson) - - Ford-Fulkerson 法は Dinic 法と並んで競技プログラミングでよく利用される最大流問題を解くアルゴリズムのひとつである。Dinic 法では最短経路 DAG を構成して増加パスをこの DAG の上で探すが、Ford-Fulkerson 法では増加パスを単純な DFS により探す。 + - Ford-Fulkerson 法は Dinic 法と並んで競技プログラミングでよく利用される最大フロー問題を解くアルゴリズムのひとつである。Dinic 法では最短経路 DAG を構成して増加パスをこの DAG の上で探すが、Ford-Fulkerson 法では増加パスを単純な DFS により探す。 ## 外部リンク diff --git a/_algorithms/ford-fulkerson.md b/_algorithms/ford-fulkerson.md index ce346d7..35f1e5b 100644 --- a/_algorithms/ford-fulkerson.md +++ b/_algorithms/ford-fulkerson.md @@ -9,14 +9,14 @@ algorithm: input: > 辺容量が整数であるネットワーク (つまり有向グラフ $G = (V, E)$ および辺容量 $c : E \to \mathbb{N}$ および相異なる頂点 $s, t \in V$) output: > - $s$-$t$ 最大流 (つまり関数 $f : E \to \mathbb{N}$ であって容量制約とフロー保存則を満たすもの) + $s$-$t$ 最大フロー (つまり関数 $f : E \to \mathbb{N}$ であって容量制約とフロー保存則を満たすもの) time_complexity: > 出力の $s$-$t$ 最大流量を $F$ として $O(F \cdot \lvert E \rvert)$ space_complexity: aliases: [] level: blue description: > - Ford-Fulkerson 法は最大流問題を解くアルゴリズムのひとつ。 + Ford-Fulkerson 法は最大フロー問題を解くアルゴリズムのひとつ。 増加パスを DFS で探してそこにフローを流していくことを繰り返す。 計算量は出力の $s$-$t$ 最大流量を $F$ として $O(F \cdot \lvert E \rvert)$ である。 --- @@ -25,7 +25,7 @@ description: > ## 概要 -Ford-Fulkerson 法は最大流問題を解くアルゴリズムのひとつである。 +Ford-Fulkerson 法は[最大フロー問題](/maximum-flow-problem)を解くアルゴリズムのひとつである。 残余グラフ上で増加パスを DFS で探しそこにフローを流していくことを繰り返す。 計算量は出力の $s$-$t$ 最大流量を $F$ として $O(F \cdot \lvert E \rvert)$ である。 @@ -37,8 +37,10 @@ Ford-Fulkerson 法は最大流問題を解くアルゴリズムのひとつで ## 関連項目 +- [最大フロー問題](/maximum-flow-problem) + - Ford-Fulkerson 法は最大フロー問題を解くアルゴリズムである。 - [Dinic 法](/dinic) - - Dinic 法は Ford-Fulkerson 法と並んで競技プログラミングでよく利用される最大流問題を解くアルゴリズムのひとつである。Ford-Fulkerson 法では増加パスを単純な DFS により探すが、Dinic 法では最短経路 DAG を構成して増加パスをこの DAG の上で探す。 + - Dinic 法は Ford-Fulkerson 法と並んで競技プログラミングでよく利用される最大フロー問題を解くアルゴリズムのひとつである。Ford-Fulkerson 法では増加パスを単純な DFS により探すが、Dinic 法では最短経路 DAG を構成して増加パスをこの DAG の上で探す。 ## 外部リンク diff --git a/_algorithms/maximum-flow-problem.md b/_algorithms/maximum-flow-problem.md new file mode 100644 index 0000000..794c980 --- /dev/null +++ b/_algorithms/maximum-flow-problem.md @@ -0,0 +1,45 @@ +--- +layout: entry +changelog: + - summary: 記事作成 + authors: kimiyuki + reviewers: + date: 2021-04-01T00:00:00+09:00 +algorithm: + input: + output: + time_complexity: + space_complexity: + aliases: ["最大流問題", "maximum flow problem"] + level: blue +description: > + 最大フロー問題とは、与えられたネットワークのフローであって流量が最大のものを求めるという問題。 + 最大フロー最小カット定理によって最大フロー問題の解の流量は最小カット問題の解の容量に等しい。 +--- + +# 最大フロー問題 + +## 概要 + +最大フロー問題とは、与えられたネットワークのフローであって流量が最大のものを求めるという問題である。 +最大フロー最小カット定理によって最大フロー問題の解の流量は[最小カット問題](/minimum-cut-problem)の解の容量に等しい。 + + +## 詳細 + +(省略) + + +## その他 + +- フローの定義では「始点から終点へと向かうフローと無関係な位置に閉路状のフローがないこと」は要求されていない。最大フローを求めるアルゴリズムはこのような閉路状のフローを含む出力をすることがあるので、出力されたフローの構成を利用する際には注意が必要である。なお、最大フロー問題の解から流量を変えずにこのような閉路状のフローを取り除くことは常に可能である。 + + +## 関連項目 + +- [最小カット問題](/minimum-cut-problem) + - 最大フロー最小カット定理によって最大フロー問題の解の流量は最小カット問題の解の容量に等しい。 +- [Dinic 法](/dinic) + - Dinic 法は最大フロー問題を解くアルゴリズムである。最悪計算量は $O(\lvert V \rvert^2 \cdot \lvert E \rvert)$ だが実用的にはかなり速い。 +- [Ford-Fulkerson 法](/ford-fulkerson) + - Ford-Fulkerson 法は最大フロー問題を $O(F \cdot \lvert E \rvert)$ で解く代表的なアルゴリズムである。 diff --git a/_algorithms/minimum-cut-problem.md b/_algorithms/minimum-cut-problem.md new file mode 100644 index 0000000..ea546e8 --- /dev/null +++ b/_algorithms/minimum-cut-problem.md @@ -0,0 +1,73 @@ +--- +layout: entry +changelog: + - summary: 記事作成 + authors: kimiyuki + reviewers: + date: 2021-04-01T00:00:00+09:00 +algorithm: + input: + output: + time_complexity: + space_complexity: + aliases: ["minimum cut problem"] + level: blue +description: > + 最小カット問題とは、与えられたネットワークのカットであって容量が最小のものを求めるという問題。 + 最大フロー最小カット定理によって最小カット問題の解の容量は最大フロー問題の解の流量に等しい。 +--- + +# 最小カット問題 + +## 概要 + +最小カット問題とは、与えられたネットワークのカットであって容量が最小のものを求めるという問題である。 +最大フロー最小カット定理によって最小カット問題の解の容量は[最大フロー問題](/maximum-flow-problem)の解の流量に等しい。 + + +## カットの定義 + +与えられたネットワークの $s$-$t$ カットの定義としては、大きく分けて以下の 3 種類がある。 + +1. 有向辺の部分集合 $C \subseteq E$ であってどの $s$-$t$ パスも $C$ に含まれるような有向辺を含むもの[^cut-set-of-edges] +2. 頂点の部分集合 $S \subseteq V$ であって $s \in S$ かつ $t \in V \setminus S$ なもの[^cut-set-of-vertices] +3. 有向辺の部分集合 $C \subseteq E$ であって、次を満たすもの: ある頂点の部分集合 $S \subseteq V$ であって $s \in S$ かつ $t \in V \setminus S$ なものが存在し、$S$ に含まれる頂点から $V \setminus S$ に含まれる頂点への有向辺の全体が $C$ に等しい[^cut-set-of-vertices-as-edges] + +カットの容量は、(1.) と (3.) の定義の場合は $C$ に含まれる有向辺の重みの総和として定義される。 +(2.) の定義の場合は始点が $S$ に含まれかつ終点が $V \setminus S$ に含まれるような有向辺の重みの総和として定義される。 + +最小カット問題を考える際にはどの定義を用いても解の容量は同じであるが、カットの定義としてはすべて異なるものである。 +(1.) の定義と (2.) の定義との違いはカットの容量の最大値について考えれば明らかである。 +(2.) の定義と (3.) の定義とはほとんど同じものであるが、ネットワークが非連結な場合に異なってくる。 +(1.) で定義されるものを (2.) や (3.) で定義されるものから区別したいときには、(1.) で定義されるものを $s$-$t$ 非連結化集合 ($s$-$t$ disconnecting edge set) と呼ぶことがある[^s-t-disconnecting-edge-set]。 + + +## 関連項目 + +- [最大フロー問題](/maximum-flow-problem) + - 最大フロー最小カット定理によって最小カット問題の解の容量は最大フロー問題の解の流量に等しい。 +- [燃やす埋める問題](/moyasu-umeru-mondai) + - 燃やす埋める問題は最小カット問題へと帰着できる。 +- [project selection problem](/project-selection-problem) + - project selection problem は最小カット問題へと帰着できる。 + + +## 外部リンク + +- [最小カットについて - よすぽの日記](https://yosupo.hatenablog.com/entry/2015/03/31/134336)[archive.org](https://web.archive.org/web/20210401023012/https://yosupo.hatenablog.com/entry/2015/03/31/134336) + - yosupo によるブログ記事。最小カット問題はグラフの $2$ 彩色だと思うとよいことが説明されている。 +- [最小カット問題と充足最大化問題 - うさぎ小屋](https://kimiyuki.net/blog/2020/03/07/minimum-cut-and-maximum-satisfiability/)[archive.org](https://web.archive.org/web/20210401023109/https://kimiyuki.net/blog/2020/03/07/minimum-cut-and-maximum-satisfiability/) + - kimiyuki によるブログ記事。最小カット問題は $\bigvee\mkern-12.5mu\bigvee _ i p_i \to \bigwedge\mkern-12.5mu\bigwedge _ j q_j$ の形の論理式たちの充足最大化問題と見ることができると主張している。 +- [燃やす埋める問題と劣モジュラ関数のグラフ表現可能性 その① - 私と理論](https://theory-and-me.hatenablog.com/entry/2020/03/13/180935)[archive.org](https://web.archive.org/web/20210401023205/https://theory-and-me.hatenablog.com/entry/2020/03/13/180935), [燃やす埋める問題と劣モジュラ関数のグラフ表現可能性 その② グラフ構築編 - 私と理論](https://theory-and-me.hatenablog.com/entry/2020/03/17/180157)[archive.org](https://web.archive.org/web/20210401023147/https://theory-and-me.hatenablog.com/entry/2020/03/17/180157) + - theory_and_me によるブログ記事。$3$ 変数までの劣モジュラ関数の和 $\sum_i \theta_i(x_i) + \sum _ {i \lt j} \phi _ {i, j} (x_i, x_j) + \sum _ {i \lt j \lt k} \psi _ {i, j, k} (x_i, x_j, x_k)$ で表される関数の最小化問題は最小カット問題に帰着できることを説明している。 +- [燃やす埋める問題を完全に理解した話 - koyumeishiのブログ](https://koyumeishi.hatenablog.com/entry/2021/01/14/052223)[archive.org](https://web.archive.org/web/20210401023419/https://koyumeishi.hatenablog.com/entry/2021/01/14/052223) + - koyumeishi によるブログ記事。$2$ 変数間の制約からグラフ表現可能な劣モジュラ関数を自動導出するライブラリを提案している。 + + +## 注釈 + +[^moyasu-umeru-local-name]: 競技プログラミングのコミュニティ外では通用しない名前であることに注意したい。 +[^cut-set-of-edges]: たとえば R. J. ウィルソン. グラフ理論入門. 近代科学社, 2001, [ISBN978-4-76-490296-1](https://iss.ndl.go.jp/api/openurl?isbn=9784764902961). +[^cut-set-of-vertices]: たとえば R. Diestel, [Graph Theory](https://www.springer.com/jp/book/9783662536216), 5th ed. Berlin Heidelberg: Springer-Verlag, 2017. +[^cut-set-of-vertices-as-edges]: たとえば Schrijver, A. [Combinatorial Optimization: Polyhedra and Efficiency](https://www.springer.com/jp/book/9783540443896), Springer Science & Business Media, 2003. +[^s-t-disconnecting-edge-set]: たとえば Schrijver, A. [Combinatorial Optimization: Polyhedra and Efficiency](https://www.springer.com/jp/book/9783540443896), Springer Science & Business Media, 2003. diff --git a/_algorithms/moyasu-umeru-mondai.md b/_algorithms/moyasu-umeru-mondai.md new file mode 100644 index 0000000..3e0f68f --- /dev/null +++ b/_algorithms/moyasu-umeru-mondai.md @@ -0,0 +1,67 @@ +--- +layout: entry +changelog: + - summary: 記事作成 + authors: kimiyuki + reviewers: + date: 2021-04-01T00:00:00+09:00 +algorithm: + input: + output: + time_complexity: + space_complexity: + aliases: + level: blue +description: > + 燃やす埋める問題は最小カット問題に帰着できる問題のひとつ。 + 与えられたいくつかのゴミをある形の制約の下でそれぞれ「燃やす」あるいは「埋める」ことによって処理するときの費用の最小値を求める問題である。 + なお、これは競技プログラミングのコミュニティの中でだけ通用する用語であることに注意したい。 +--- + +# 燃やす埋める問題 + +## 概要 + +競技プログラミングのコミュニティにおいて「燃やす埋める問題」という名前[^moyasu-umeru-local-name]で呼ばれている問題は、次のような形の問題である: + +- $N$ 個のゴミ $0, 1, 2, \dots, N - 1$ があり、それぞれについて「燃やす」か「埋める」かを選んで処理しなければならない。 + ゴミ $i$ は燃やすと $a_i$ 円 ($a_i \ge 0$) かかり埋めると $b_i$ 円 ($b_i \ge 0$) かかる。 + さらに、ゴミ $x_j$ を燃やしたときにゴミ $y_j$ を埋めると罰金として $c_j$ 円 ($c_j \ge 0$) かかるという形の条件が $K$ 個与えられている。 + このときゴミをすべて処理するのに必要な費用の最小値を求めよ。 + + +## 最小カット問題への帰着 + +燃やす埋める問題はある $N + 2$ 頂点 $2N + K$ 辺のネットワークを考えることで[最小カット問題](/minimum-cut-problem)に帰着できる。 +$N$ 個のゴミをそれぞれ頂点とし、始点 $s$ および終点 $t$ を追加する。 +始点 $s$ からそれぞれのゴミ $i$ へ容量 $a_i$ の辺を張り、それぞれのゴミ $i$ から終点 $t$ へ容量 $b_i$ の辺を張り、それぞれの制約 $j$ ごとに頂点 $y_j$ から頂点 $x_j$ へ容量 $c_j$ の辺を貼る。 +こうしてできるネットワーク上での最小カットの容量は燃やす埋める問題の答えに等しい。 +このネットワークを図示すると以下のようになる。 + +![燃やす埋める問題のネットワーク](assets/img/moyasu-umeru-mondai.svg) + + +## その他 + +- 燃やす埋める問題は広義には「選択肢とそれに関わる制約が与えられて最大化や最小化をする問題であって、最小カット問題へと帰着できるもの」を指すことがある。$s$-$t$ カットを頂点の部分集合 $S \subseteq V$ であって $s \in S$ かつ $t \in V \setminus S$ なものとして定義して最小カット問題を考えるとき、このような広義の燃やす埋める問題と最小カット問題とはほとんど区別が付かなくなる。 + + +## 関連項目 + +- [最小カット問題](/minimum-cut-problem) + - 燃やす埋める問題は最小カット問題へと帰着できる。 +- [project selection problem](/project-selection-problem) + - project selection problem は燃やす埋める問題と同じく最小カット問題に帰着できる問題のひとつである。 + + +## 外部リンク + +- 最小カット - CKomakiの日記 - TopCoder部 (Internet Archive にも保存されておらず現在は閲覧不能) + - Komaki によるブログ記事。燃やす埋める問題という問題はこの記事で提案されたようである。 +- [最小カットを使って「燃やす埋める問題」を解く - SlideShare](https://www.slideshare.net/shindannin/project-selection-problem)[archive.org](https://web.archive.org/web/20210401023045/https://www.slideshare.net/shindannin/project-selection-problem) + - shindannin によるスライド。燃やす埋める問題について分かりやすく説明している。 + + +## 注釈 + +[^moyasu-umeru-local-name]: 競技プログラミングのコミュニティ外では通用しない名前であることに注意したい。 diff --git a/_algorithms/project-selection-problem.md b/_algorithms/project-selection-problem.md new file mode 100644 index 0000000..798ed49 --- /dev/null +++ b/_algorithms/project-selection-problem.md @@ -0,0 +1,62 @@ +--- +layout: entry +changelog: + - summary: 記事作成 + authors: kimiyuki + reviewers: + date: 2021-04-01T00:00:00+09:00 +algorithm: + input: + output: + time_complexity: + space_complexity: + aliases: + level: blue +description: > + project selection problem は最小カット問題に帰着できる問題のひとつ。 +--- + +# project selection problem + +## 概要 + +project selection problem とは、次の形の問題である: + +- $N$ 個のプロジェクト $x_0, x_1, x_2, \dots, x _ {N-1}$ と $M$ 個の機械 $y_0, y_1, y_2, \dots, y _ {M-1}$ がある。 + プロジェクト $x_i$ を実行すると利益 $a_i$ 円 ($a_i \ge 0$) を産む。 + 機械 $y_j$ は購入に費用 $b_j$ 円 ($b_j \ge 0$) かかる。 + さらに、プロジェクト $x _ {c_k}$ を実行するためは機械 $y _ {d_k}$ が購入されていなければならないという形の条件が $K$ 個与えらている。 + ただし機械は複数のプロジェクト間で共有できる。 + 実行するプロジェクトと購入する機械を適切に選択したときの利益の最大値を求めよ。 + + +## 最小カット問題への帰着 + +project selection problem はある $N + M + 2$ 頂点 $N + M + K$ 辺のネットワークを考えることで[最小カット問題](/minimum-cut-problem)に帰着できる。 +$N$ 個のプロジェクトと $M$ 個の機械をそれぞれ頂点とし、始点 $s$ および終点 $t$ を追加する。 +始点 $s$ からプロジェクト $x_i$ の頂点へ容量 $a_i$ の辺を張り、機械 $y_j$ の頂点から終点 $t$ へ容量 $b_j$ の辺を張り、それぞれの制約 $k$ ごとにプロジェクト $x _ {c_k}$ の頂点から機械 $y _ {d_k}$ の頂点へ容量無限大の辺を張る[^infinity-capacity]。 +こうしてできるネットワーク上での最小カットの容量を $F$ とすると project selection problem の答えは $\sum_i a_i - F$ となる。 +このネットワークを図示すると以下のようになる。 + +![project selection problem のネットワーク](assets/img/project-selection-problem.svg) + + +## 関連項目 + +- [最小カット問題](/minimum-cut-problem) + - project selection problem は最小カット問題へと帰着できる。 +- [燃やす埋める問題](/moyasu-umeru-mondai) + - 燃やす埋める問題は project selection problem と同じく最小カット問題に帰着できる問題のひとつである。 + + +## 外部リンク + +- [『燃やす埋める』と『ProjectSelectionProblem』 - とこはるのまとめ](http://tokoharuland.hateblo.jp/entry/2017/11/12/234636)[archive.org](https://web.archive.org/web/20210401023114/http://tokoharuland.hateblo.jp/entry/2017/11/12/234636) + - tokoharu によるブログ記事。燃やす埋める問題という問題ではなく project selection problem を利用することを提案している。 +- [最小カットを使って「燃やす埋める」問題を解くスライドのフォロー - じじいのプログラミング](https://shindannin.hatenadiary.com/entry/2017/11/15/043009)[archive.org](https://web.archive.org/web/20210401023113/https://shindannin.hatenadiary.com/entry/2017/11/15/043009) + - shindannin によるブログ記事。燃やす埋める問題と project selection problem とを比較している。 + + +## 注釈 + +[^infinity-capacity]: ネットワークや最小カット問題の通常の定義では容量無限大の辺は許容されない。より正確には、入力の他の部分に依存する充分大きな数 $C$ をとって、容量無限大の辺の代わりに容量 $C$ の辺を張る。 diff --git a/_layouts/default.html b/_layouts/default.html index 74ad12b..eaae1f8 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -98,6 +98,11 @@

a.href = baseurl.replace(/\/$/, "") + a.pathname; } } + for (const img of main.getElementsByTagName("img")) { + if (new URL(baseurl).host == img.src.host && !img.src.startsWith(baseurl)) { + img.src = baseurl.replace(/\/$/, "") + img.src.pathname; + } + } } })(); diff --git a/_sass/user-colors.scss b/_sass/user-colors.scss index 53d8f15..5f4704d 100644 --- a/_sass/user-colors.scss +++ b/_sass/user-colors.scss @@ -1,6 +1,7 @@ // THIS FILE IS GENERATED BY user-ratings.py! DO NOT EDIT! @import "rating-colors"; .handle { font-weight: bold; } +.user-Komaki { color: $rating-color-orange; } .user-MiSawa { color: $rating-color-green; } .user-chokudai { color: $rating-color-red; } .user-drken { color: $rating-color-orange; } @@ -14,6 +15,7 @@ .user-kanra824 { color: $rating-color-yellow; } .user-kimiyuki { color: $rating-color-orange; } .user-kort0n { color: $rating-color-red; } +.user-koyumeishi { color: $rating-color-yellow; } .user-kuretchi { color: $rating-color-blue; } .user-kuuso { color: $rating-color-blue; } .user-minaminao { color: $rating-color-yellow; } @@ -22,11 +24,14 @@ .user-noshi91 { color: $rating-color-red; } .user-potetisensei { color: $rating-color-orange; } .user-rsk0315 { color: $rating-color-yellow; } +.user-shindannin { color: $rating-color-blue; } .user-sigma425 { color: $rating-color-red; } .user-sky58 { color: $rating-color-red; } .user-snuke { color: $rating-color-red; } .user-tempura0224 { color: $rating-color-red; } +.user-theory_and_me { color: $rating-color-blue; } .user-tmaehara { color: $rating-color-black; } +.user-tokoharu { color: $rating-color-orange; } .user-udon1206 { color: $rating-color-blue; } .user-uwi { color: $rating-color-red; } .user-yosupo { color: $rating-color-red; } diff --git a/assets/img/.gitignore b/assets/img/.gitignore new file mode 100644 index 0000000..3235c3d --- /dev/null +++ b/assets/img/.gitignore @@ -0,0 +1,5 @@ +# Tikz/PGF +*.aux +*.div +*.log +*.pdf diff --git a/assets/img/README.md b/assets/img/README.md new file mode 100644 index 0000000..8ed89e2 --- /dev/null +++ b/assets/img/README.md @@ -0,0 +1,24 @@ +# assets/img + +## この README.md について + +後から画像を修正する必要が発生したときのために、画像の編集方法をこのファイルに書いておきましょう。 + + +## moyasu-umeru-mondai.svg + +TikZ/PGF を使っています。 +以下のようにコンパイルしてください。 + +```console +$ pdflatex moyasu-umeru-mondai.tex +$ pdf2svg moyasu-umeru-mondai.pdf moyasu-umeru-mondai.svg +``` + + +## project-selection-problem.svg + +```console +$ pdflatex project-selection-problem.tex +$ pdf2svg project-selection-problem.pdf project-selection-problem.svg +``` diff --git a/assets/img/moyasu-umeru-mondai.svg b/assets/img/moyasu-umeru-mondai.svg new file mode 100644 index 0000000..5be892a --- /dev/null +++ b/assets/img/moyasu-umeru-mondai.svg @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/img/moyasu-umeru-mondai.tex b/assets/img/moyasu-umeru-mondai.tex new file mode 100644 index 0000000..52c1057 --- /dev/null +++ b/assets/img/moyasu-umeru-mondai.tex @@ -0,0 +1,58 @@ +\documentclass[tikz]{standalone} + +\begin{document} +\begin{tikzpicture}[ + x=7.0cm, + y=2.4cm, + font=\large, + v/.style={draw, circle, fill=white, minimum size=1.6cm}, + dots/.style={circle, minimum size=1.6cm}, + e/.style={draw, ->}, +] + \node[v] (s) at (-1, 0) {$s$}; + \node[v] (x0) at (0, 3) {$0$}; + \node[v] (x1) at (0, 2) {$1$}; + \node[v] (x2) at (0, 1) {$2$}; + \node[v] (x3) at (0, 0) {$3$}; + \node at (0, -1.5) {$\vdots$}; + \node[dots] (dots0) at (0, -1.0) {}; + \node[dots] (dots1) at (0, -1.2) {}; + \node[dots] (dots2) at (0, -1.4) {}; + \node[dots] (dots3) at (0, -1.6) {}; + \node[dots] (dots4) at (0, -1.8) {}; + \node[dots] (dots5) at (0, -2.0) {}; + \node[dots] (dots6) at (0, -2.2) {}; + \node[dots] (dots7) at (0, -2.4) {}; + \node[v] (xl) at (0, -3) {$N-1$}; + \node[v] (t) at (1, 0) {$t$}; + + \path[e] (s) edge node[midway, above] {$a_0$} (x0); + \path[e] (s) edge node[midway, above] {$a_1$} (x1); + \path[e] (s) edge node[midway, above] {$a_2$} (x2); + \path[e] (s) edge node[midway, above] {$a_3$} (x3); + \path[e] (s) edge node[midway, above] {$a_3$} (x3); + \path[e] (s) edge (dots0); + \path[e] (s) edge (dots2); + \path[e] (s) edge (dots4); + \path[e] (s) edge (dots6); + \path[e] (s) edge node[midway, above] {$a_{N-1}$} (xl); + \path[e] (x0) edge node[midway, above] {$b_0$} (t); + \path[e] (x1) edge node[midway, above] {$b_1$} (t); + \path[e] (x2) edge node[midway, above] {$b_2$} (t); + \path[e] (x3) edge node[midway, above] {$b_3$} (t); + \path[e] (dots0) edge (t); + \path[e] (dots2) edge (t); + \path[e] (dots4) edge (t); + \path[e] (dots6) edge (t); + \path[e] (xl) edge node[midway, above] {$b_{N-1}$} (t); + + \path[e, out=30, in=-30] (x2) edge node[midway, right] {$c_0$} (x0); + \path[e, out=30, in=-30] (x3) edge node[midway, right] {$c_1$} (x2); + \path[e, out=-150, in=150] (x1) edge node[midway, left] {$c_2$} (x3); + \path[e, out=30, in=-30] (dots1) edge (x3); + \path[e, out=30, in=-30] (dots7) edge (x2); + \path[e, out=30, in=-30] (xl) edge node[near start, right] {$c_{K-1}$} (dots1); + \path[e, out=-150, in=150] (x2) edge (dots2); + \path[e, out=-150, in=150] (x3) edge (dots7); +\end{tikzpicture} +\end{document} diff --git a/assets/img/project-selection-problem.svg b/assets/img/project-selection-problem.svg new file mode 100644 index 0000000..aca1ea4 --- /dev/null +++ b/assets/img/project-selection-problem.svg @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/img/project-selection-problem.tex b/assets/img/project-selection-problem.tex new file mode 100644 index 0000000..696f140 --- /dev/null +++ b/assets/img/project-selection-problem.tex @@ -0,0 +1,73 @@ +\documentclass[tikz]{standalone} + +\begin{document} +\begin{tikzpicture}[ + x=4.8cm, + y=2.4cm, + font=\large, + v/.style={draw, circle, fill=white, minimum size=1.6cm}, + dots/.style={circle, minimum size=1.6cm}, + e/.style={draw, ->}, +] + \node[v] (s) at (0, 0) {$s$}; + \node[v] (x0) at (1, 2.5) {$x_0$}; + \node[v] (x1) at (1, 1.5) {$x_1$}; + \node[v] (x2) at (1, 0.5) {$x_2$}; + \node[v] (x3) at (1, -0.5) {$x_3$}; + \node at (1, -1.5) {$\vdots$}; + \node[dots] (xdots0) at (1, -1.0) {}; + \node[dots] (xdots1) at (1, -1.2) {}; + \node[dots] (xdots2) at (1, -1.4) {}; + \node[dots] (xdots3) at (1, -1.6) {}; + \node[dots] (xdots4) at (1, -1.8) {}; + \node[dots] (xdots5) at (1, -2.0) {}; + \node[v] (xl) at (1, -2.5) {$x_{N-1}$}; + \node[v] (y0) at (2, 3) {$y_0$}; + \node[v] (y1) at (2, 2) {$y_1$}; + \node[v] (y2) at (2, 1) {$y_2$}; + \node[v] (y3) at (2, 0) {$y_3$}; + \node at (2, -1.5) {$\vdots$}; + \node[dots] (ydots0) at (2, -1.0) {}; + \node[dots] (ydots1) at (2, -1.2) {}; + \node[dots] (ydots2) at (2, -1.4) {}; + \node[dots] (ydots3) at (2, -1.6) {}; + \node[dots] (ydots4) at (2, -1.8) {}; + \node[dots] (ydots5) at (2, -2.0) {}; + \node[dots] (ydots6) at (2, -2.2) {}; + \node[dots] (ydots7) at (2, -2.4) {}; + \node[v] (yl) at (2, -3) {$y_{M-1}$}; + \node[v] (t) at (3, 0) {$t$}; + + \path[e] (s) edge node[midway, above] {$a_0$} (x0); + \path[e] (s) edge node[midway, above] {$a_1$} (x1); + \path[e] (s) edge node[midway, above] {$a_2$} (x2); + \path[e] (s) edge node[midway, above] {$a_3$} (x3); + \path[e] (s) edge node[midway, above] {$a_3$} (x3); + \path[e] (s) edge (xdots0); + \path[e] (s) edge (xdots2); + \path[e] (s) edge (xdots4); + \path[e] (s) edge node[midway, below] {$a_{N-1}$} (xl); + \path[e] (y0) edge node[midway, above] {$b_0$} (t); + \path[e] (y1) edge node[midway, above] {$b_1$} (t); + \path[e] (y2) edge node[midway, above] {$b_2$} (t); + \path[e] (y3) edge node[midway, above] {$b_3$} (t); + \path[e] (ydots0) edge (t); + \path[e] (ydots2) edge (t); + \path[e] (ydots4) edge (t); + \path[e] (ydots6) edge (t); + \path[e] (yl) edge node[midway, below] {$b_{M-1}$} (t); + + \path[e] (x0) edge node[midway, above] {$\infty$} (y0); + \path[e] (x1) edge node[midway, above] {$\infty$} (y0); + \path[e] (x1) edge node[midway, above] {$\infty$} (y3); + \path[e] (x2) edge node[midway, above] {$\infty$} (y0); + \path[e] (x3) edge node[midway, above] {$\infty$} (y2); + \path[e] (x3) edge node[midway, above] {$\infty$} (ydots0); + \path[e] (xdots0) edge node[midway, above] {$\infty$} (y2); + \path[e] (xdots2) edge node[midway, above] {$\infty$} (ydots0); + \path[e] (xdots3) edge node[midway, above] {$\infty$} (ydots5); + \path[e] (xdots5) edge node[midway, above] {$\infty$} (yl); + \path[e] (xl) edge node[midway, above] {$\infty$} (ydots2); + \path[e] (xl) edge node[midway, above] {$\infty$} (ydots5); +\end{tikzpicture} +\end{document} diff --git a/scripts/lint.py b/scripts/lint.py index 4738542..377cbd4 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -223,7 +223,7 @@ def error_by_regex(pattern: str, text: str, fix: Union[None, str, Callable[[Matc result.extend(check_atcoder_user(m.group(1), file=path, line=line, col=m.start() + 1)) # internal links - for m in re.finditer(r'(!?)\[([^]]*)\]\((/[-0-9a-z]+)\)', msg): + for m in re.finditer(r'(!?)\[([^]]*)\]\((/[- 0-9A-Z_a-z]+)\)', msg): is_image = m.group(1) actual_title = m.group(2) urlpath = m.group(3) @@ -259,7 +259,7 @@ def error_by_regex(pattern: str, text: str, fix: Union[None, str, Callable[[Matc 'github.com', 'iss.ndl.go.jp', 'ja.wikipedia.org', - 'springer.com', + 'www.springer.com', ) for url, col in found_urls: hostname = urllib.parse.urlparse(url).hostname @@ -349,6 +349,13 @@ def error_by_regex(pattern: str, text: str, fix: Union[None, str, Callable[[Matc text=r"日本語: `用量` ではなく `容量` の可能性があります。", ) + if 'http' not in msg: + error_by_regex( + pattern=r'最大流(問題|最小カット定理|を|は|が|や)', + text=r"typo: `最大流` ではなく `最大フロー` を使ってください。`最大フロー` の方が一般的です。(https://github.com/kmyk/algorithm-encyclopedia/pull/140#discussion_r606915806)", + fix=(lambda m: r'最大フロー' + m.group(1)), + ) + if 'http' not in msg: error_by_regex( pattern='([A-Za-z]+)法',