Skip to content

Commit d001d90

Browse files
hitonanodeweb-flow
andauthored
マトロイド系 修正 (#99)
* Add documents for matroids * bugfix for binary matroid * Bug fix for graphic matroid * combinatorial_opt/matroids/graphic_matroid.hpp * Fix name of graphic matroid * fix documents * [auto-verifier] verify commit 9e97674 Co-authored-by: GitHub <noreply@github.com>
1 parent 8655ce3 commit d001d90

9 files changed

+118
-27
lines changed

combinatorial_opt/matroid_intersection.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <vector>
55

66
// CUT begin
7-
// (Min weight) Matroid intersection solver
7+
// (Min weight) matroid intersection solver
88
// Algorithm based on http://dopal.cs.uec.ac.jp/okamotoy/lect/2015/matroid/
99
// Complexity: O(CE^2 + E^3) (C : circuit query, non-weighted)
1010
template <class M1, class M2, class T = int>

combinatorial_opt/matroid_intersection.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ std::vector<bool> maxindepset = MatroidIntersection(m1, m2, weights);
2525
## 問題例
2626
2727
- [Hello 2020 G. Seollal - Codeforces](https://codeforces.com/contest/1284/problem/G) グラフマトロイドと分割マトロイドの交差に帰着される.
28-
- [Deltix Round, Summer 2021 H. DIY Tree - Codeforces](https://codeforces.com/contest/1556/problem/H) グラフマトロイドと分割マトロイドの最小重み共通独立集合問題に帰着される.
28+
- [Deltix Round, Summer 2021 H. DIY Tree - Codeforces](https://codeforces.com/contest/1556/problem/H) 少数の頂点に次数制約がついた最小全域木問題.グラフマトロイドと分割マトロイドの最小重み共通独立集合問題に帰着される.
29+
- [2019 Petrozavodsk Winter Camp, Yandex Cup D. Pick Your Own Nim - Codeforces](https://codeforces.com/gym/102156/problem/D) 二値マトロイドと分割マトロイドの交差.
30+
- [2128 - Demonstration of Honesty! - URI Online Judge](https://www.urionlinejudge.com.br/judge/en/problems/view/2128) 各辺に色がついている無向グラフで,同色の辺は一度しか使えない全域木構築判定問題.グラフマトロイドと分割マトロイドの交差.このライブラリでは TL が厳しいが,独立性を満たす範囲で乱択のアプローチ等によりある程度 $I$ に要素を追加した状態から増加路アルゴリズムを回すことで定数倍高速化し TL に間に合わせられる.
31+
- [CodeChef October Challenge 2019: Faulty System](https://www.codechef.com/problems/CNNCT2) グラフマトロイドとグラフマトロイドの交差.
32+
- [Rainbow Graph – Kattis, NAIPC 2018](https://naipc18.kattis.com/problems/rainbowgraph)
33+
- [Google Code Jam 2019 Round 3 Datacenter Duplex](https://codingcompetitions.withgoogle.com/codejam/round/0000000000051707/0000000000158f1c)
2934
3035
## 文献・リンク集
3136
@@ -34,3 +39,4 @@ std::vector<bool> maxindepset = MatroidIntersection(m1, m2, weights);
3439
- [2] C. Brezovec, G. Cornuéjols, and F. Glover, "Two algorithms for weighted matroid intersection,"
3540
Mathematical Programming, 36(1), 39-53, 1986.
3641
- [離散最適化基礎論 (2015年度後学期) 組合せ最適化におけるマトロイドの役割](http://dopal.cs.uec.ac.jp/okamotoy/lect/2015/matroid/) とても初学者向き.
42+
- [[Tutorial] Matroid intersection in simple words - Codeforces](https://codeforces.com/blog/entry/69287) コメント欄に問題例が多い.

combinatorial_opt/matroids/vector_matroid.hpp renamed to combinatorial_opt/matroids/binary_matroid.hpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
#include <vector>
44

55
// CUT begin
6-
// Vector matroid on F2 : linearly independent vectors
6+
// Binary matroid (vector matroid on F2) : linearly independent vectors
77
// VDIM: max. dimension of vector space
88
// Verified: SRM526.5 1000 (Used only for linear independence check)
9-
template <int VDIM> class F2VectorMatroid {
9+
// Verified: CF102156D 2019 Petrozavodsk Winter Camp, Yandex Cup D. Pick Your Own Nim
10+
template <int VDIM> class BinaryMatroid {
1011
using Element = int;
1112
static void chxormin(std::bitset<VDIM> &l, const std::bitset<VDIM> &r) {
1213
int i = r._Find_first();
@@ -17,8 +18,8 @@ template <int VDIM> class F2VectorMatroid {
1718
std::vector<std::vector<std::bitset<VDIM>>> bs;
1819

1920
public:
20-
F2VectorMatroid() = default;
21-
F2VectorMatroid(const std::vector<std::bitset<VDIM>> &bitmat) : mat(bitmat) {}
21+
BinaryMatroid() = default;
22+
BinaryMatroid(const std::vector<std::bitset<VDIM>> &bitmat) : mat(bitmat) {}
2223

2324
int size() const { return mat.size(); }
2425

@@ -28,26 +29,25 @@ template <int VDIM> class F2VectorMatroid {
2829
if (I[e]) Iset.push_back(e);
2930
}
3031
bs.assign(Iset.size() + 1, {});
31-
for (int i = 0; i < int(Iset.size()); i++) {
32-
for (int j = i; j < int(Iset.size()); j++) {
32+
for (int i = 0; i < int(Iset.size()) + 1; i++) {
33+
for (int j = 0; j < int(Iset.size()); j++) {
34+
if (i == j) continue;
3335
auto v = mat[Iset[j]];
34-
for (auto b : bs[i]) chxormin(v, b);
35-
bs[i].push_back(v);
36+
for (const auto &b : bs[i]) chxormin(v, b);
37+
if (v.any()) bs[i].push_back(v);
3638
}
3739
}
3840
}
3941
std::vector<Element> circuit(const Element &e) const {
4042
std::bitset<VDIM> v = mat[e];
41-
for (auto b : bs[0]) chxormin(v, b);
43+
for (const auto &b : bs.back()) chxormin(v, b);
4244
if (v.any()) return {}; // I + {e} is independent
4345

4446
std::vector<Element> ret{e};
45-
v = mat[e];
4647
for (int i = 0; i < int(Iset.size()); i++) {
47-
std::bitset<VDIM> w = v;
48-
for (auto b : bs[i + 1]) chxormin(w, b);
48+
std::bitset<VDIM> w = mat[e];
49+
for (const auto &b : bs[i]) chxormin(w, b);
4950
if (w.any()) ret.push_back(Iset[i]);
50-
chxormin(v, bs[0][i]);
5151
}
5252
return ret;
5353
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
title: Binary matroid (二値マトロイド)
3+
documentation_of: ./binary_matroid.hpp
4+
---
5+
6+
$\mathbb{F}_2$ 上の $N$ 行 $M$ 列の行列 $A$ によって定義されるマトロイド.集合 $I \subset 2^M$ は,$A$ のうち $I$ に含まれる番号の列のみを抜き出した部分行列が列フルランクのとき,およびその時に限り独立集合である.
7+
8+
## 使用例
9+
10+
```cpp
11+
bitset<5> v0, v1, v2, v3;
12+
v0.set(0);
13+
v1.set(1), v1.set(2);
14+
v2.set(0), v2.set(1), v2.set(2);
15+
v3.set(0), v3.set(2);
16+
vector<bitset<5>> mat{v0, v1, v2, v3};
17+
BinaryMatroid<5> M(mat);
18+
19+
vector<bool> I{0, 1, 1, 0};
20+
M.set(I);
21+
assert((M.circuit(0) == vector<int>{0, 1, 2}));
22+
```

combinatorial_opt/matroids/graph_matroid.hpp renamed to combinatorial_opt/matroids/graphic_matroid.hpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#include <utility>
44
#include <vector>
55

6-
// GraphMatroid: subgraph of undirected graphs, without loops
7-
class GraphMatroid {
6+
// GraphicMatroid: subgraph of undirected graphs, without loops
7+
class GraphicMatroid {
88
using Vertex = int;
99
using Element = int;
1010
int M;
@@ -16,24 +16,29 @@ class GraphMatroid {
1616
std::vector<int> depth, root;
1717

1818
public:
19-
GraphMatroid(int V, std::vector<std::pair<Vertex, Vertex>> edges_)
19+
GraphicMatroid(int V, const std::vector<std::pair<Vertex, Vertex>> &edges_)
2020
: M(edges_.size()), V(V), to(V), edges(edges_) {
2121
for (int e = 0; e < int(edges_.size()); e++) {
22-
assert(edges_[e].first < V and edges_[e].second < V);
23-
to[edges_[e].first].emplace_back(edges_[e].second, e);
24-
to[edges_[e].second].emplace_back(edges_[e].first, e);
22+
int u = edges_[e].first, v = edges_[e].second;
23+
assert(0 <= u and u < V);
24+
assert(0 <= v and v < V);
25+
if (u != v) {
26+
to[u].emplace_back(v, e);
27+
to[v].emplace_back(u, e);
28+
}
2529
}
2630
}
2731
int size() const { return M; }
2832

33+
std::vector<Vertex> que;
2934
template <class State> void set(State I) {
3035
assert(int(I.size()) == M);
3136
backtrack.assign(V, -1);
32-
vprev.resize(V);
37+
vprev.assign(V, -1);
3338
depth.assign(V, -1);
34-
root.resize(V);
35-
static std::vector<Vertex> que(V);
36-
int qb, qe;
39+
root.assign(V, -1);
40+
que.resize(V);
41+
int qb = 0, qe = 0;
3742
for (Vertex i = 0; i < V; i++) {
3843
if (backtrack[i] >= 0) continue;
3944
que[qb = 0] = i, qe = 1, depth[i] = 0;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
title: Graphic matroid (グラフマトロイド)
3+
documentation_of: ./graphic_matroid.hpp
4+
---
5+
6+
無向グラフ $(V, E)$ によって定義されるマトロイド.辺集合 $E$ の部分集合 $I$ は,無向グラフ上に $I$ に属する辺のみによる閉路が存在しないときに独立.
7+
8+
## 使用例
9+
10+
```cpp
11+
vector<pair<int, int>> edges;
12+
edges.emplace_back(0, 1);
13+
edges.emplace_back(0, 2);
14+
edges.emplace_back(1, 3);
15+
edges.emplace_back(1, 4);
16+
edges.emplace_back(3, 4);
17+
edges.emplace_back(2, 4);
18+
19+
GraphicMatroid M(5, edges);
20+
vector<bool> state{1, 1, 1, 1, 0, 0};
21+
M.set(state);
22+
vector<int> c1 = M.circuit(4); // [4, 2, 3]
23+
vector<int> c2 = M.circuit(5); // [5, 3, 1, 0]
24+
```

combinatorial_opt/matroids/matroid_example.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ struct MatroidExample {
66

77
int size() const; // # of elements of set we consider
88

9+
// If I is NOT independent or e \in I, undefined.
910
// If I is independent and I + {e} is not, return elements of the circuit.
10-
// If e \in I, or I + {e} is independent, return empty vector.
11-
// If I is NOT independent, undefined.
11+
// If I + {e} is also independent, return empty vector.
1212
template <class State = std::vector<bool>> void set(State I);
1313
std::vector<Element> circuit(Element e) const;
1414
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
title: マトロイドクラスのインターフェースの説明
3+
documentation_of: ./matroid_example.hpp
4+
---
5+
6+
本リポジトリで一般的なマトロイドに対して適用されるアルゴリズムは,以下のようなメソッドを持つマトロイドクラスを前提に動作する.
7+
8+
- `int size() const` 台集合の要素数を返す関数.
9+
- `template <class State = std::vector<bool>> void set(const State &I);` 現在の部分集合を独立集合 $I$ で更新する.
10+
- `std::vector<Element> circuit(Element e) const;` ($I$ が独立で)$I + e$ が従属集合である場合,サーキットを返す. $I + e$ も独立の場合,空ベクトルを返す.マトロイド交差アルゴリズムなど,体感的にはサーキットクエリの重さが時間計算量にダイレクトに影響するため,`set()` による前処理と `circuit()` による取得の両者の効率化が重要である.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
title: Partition matroid (分割マトロイド)
3+
documentation_of: ./partition_matroid.hpp
4+
---
5+
6+
$e = 0, \dots, M - 1$ からなる $M$ 要素の集合 $E$ の分割 $E$ = $E_1 \cup \dots \cup E_K \, (E_i \cap E_j = \varnothing (i \neq j))$と,分割された各部分集合に対する上限要素数 $R_k \ge 0 \, (k = 0, \dots, K - 1)$ によって定められるマトロイド:
7+
8+
$\displaystyle
9+
\mathcal{I} = \{ I \subset E \mid |I \cup E_k| \le R_k \, (k = 0, \dots, K - 1) \}.
10+
$
11+
12+
## 使用例
13+
14+
```cpp
15+
vector<vector<int>> grp{{0, 2, 5}, {1, 3}}; // 登場しない要素があってもよい(それらは制約なしとして扱われる)
16+
vector<int> lim{2, 1};
17+
PartitionMatroid M(6, grp, lim);
18+
19+
assert(M.size() == 6);
20+
vector<bool> I(6);
21+
I[0] = I[1] = I[2] = 1;
22+
M.set(I);
23+
assert((M.circuit(5) == vector<int>{0, 2, 5}));
24+
```

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy