Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
moyasu_umeru.hpp
[詳解]
1#include"../../../kyopro_library/template.hpp"
2#include"../../../kyopro_library/graph/flow/max_flow.hpp"
3
4/// @brief 燃やす埋める
5struct MoyasuUmeru {
6 MoyasuUmeru(int n) {
7 this->n=n;
8 start=n;
9 goal=n+1;
10 mf=MaxFlow(n+2);
11 }
12
13 /// @brief x[i] = 0 のときコスト zero, x[i] = 1 のときコスト one がかかるという条件を追加する
14 void add_single(int i, ll zero, ll one) {
15 if(zero<=one) {
16 //基本コストがzeroで、iを0から1に変えると+one-zeroされる
17 offset+=zero;
18 mf.add_edge(start,i,one-zero);
19 } else {
20 //基本コストがoneで、iを1から0に変えると-one+zeroされる
21 offset+=one;
22 mf.add_edge(i,goal,zero-one);
23 }
24 }
25
26 /**
27 * @brief
28 * x[ i ], x[ j ] の組み合わせについて、以下のコストかかるという条件を追加する
29 * | | x[j] = 0 | x[j] = 1 |
30 * | --- | --- | --- |
31 * | x[i] = 0 | a | b |
32 * | x[i] = 1 | c | d |
33 *
34 * @attention b + c >= a + d を要求する
35 */
36 void add_double(int i, int j, ll a, ll b, ll c, ll d) {
37 assert(b+c>=a+d);
38 offset+=a;
39 add_single(i,0,c-a);
40 add_single(j,0,d-c);
41 mf.add_edge(i,j,b+c-a-d);
42 }
43
44 /// @brief 解を復元する
45 /// @attention `solve()` を実行した後に使うこと
46 vector<int> fukugen() {
47 auto ret=mf.mincut(start);
48 ret.pop_back(); ret.pop_back();
49 for(int& x: ret) x^=1;
50 return ret;
51 }
52
53 /// @brief コスト最小値を求める
54 ll solve() { return mf.flow(start,goal)+offset; }
55
56private:
57 int n,start,goal;
58 ll offset=0;
59 MaxFlow mf;
60};
最大流
Definition max_flow.hpp:5
燃やす埋める
MoyasuUmeru(int n)
void add_single(int i, ll zero, ll one)
x[i] = 0 のときコスト zero, x[i] = 1 のときコスト one がかかるという条件を追加する
vector< int > fukugen()
解を復元する
void add_double(int i, int j, ll a, ll b, ll c, ll d)
x[ i ], x[ j ] の組み合わせについて、以下のコストかかるという条件を追加する
ll solve()
コスト最小値を求める