网络流模板-最小费用最大流
upd: 写你的网络单纯形去
最小费用最大流(原始对偶):
namespace flow{ // mcmf}{{{
using typ = int;
constexpr int V = 1, E = 1;
#error V,E unset
constexpr int EDGE_NIL = -1;
constexpr typ INF = (typ)0x3f3f3f3f3f3f3f3f;
struct Edge{ int to, nxt; typ cost, lf; } es[E*2+2*(1+EDGE_NIL)];
struct mypair{
typ dis; int id;
bool operator<(const mypair& a) const{ return dis > a.dis; }
mypair(typ d, int x){dis = d, id = x;}
};
typ dis[V], h[V];
int head[V], back[V];
sd bitset<V> vis;
int is, it, iv, cnt;
typ maxf, minc;
void init(int v, int s, int t){
is = s, it = t, iv = v;
cnt = (EDGE_NIL|1) + 1;
maxf = minc = 0;
sd fill(head, head+iv, EDGE_NIL);
}
void addflow(int s, int t, typ f, typ c){
es[cnt] = {t, head[s], c, f}, head[s] = cnt++;
es[cnt] = {s, head[t], -c, 0}, head[t] = cnt++;
}
bool dijk(){
sd priority_queue<mypair> todo;
sd fill(dis, dis+iv, INF);
vis.reset();
dis[is] = 0;
back[is] = EDGE_NIL;
todo.push({0, is});
while(!todo.empty()){
int s = todo.top().id;
todo.pop();
if(vis[s]) continue;
vis[s] = true;
for(int i=head[s]; i!=EDGE_NIL; i=es[i].nxt){
int t = es[i].to;
typ w = (typ)es[i].cost + h[s] - h[t];
if(es[i].lf && dis[t] > dis[s] + w){
dis[t] = dis[s] + w;
back[t] = i^1;
if(!vis[t]) todo.push({dis[t], t});
}
}
}
return dis[it] != INF;
}
void spfa(){
sd queue<int> todo;
vis.reset();
sd fill(h, h+iv, INF);
h[is] = 0;
todo.push(is);
while(!todo.empty()){
int s = todo.front();
todo.pop();
vis[s] = false;
for(int i=head[s]; i!=EDGE_NIL; i=es[i].nxt){
int t = es[i].to;
if(es[i].lf && h[t] > h[s] + es[i].cost){
h[t] = h[s] + es[i].cost;
if(!vis[t]) vis[t] = 1, todo.push(t);
}
}
}
}
void mcmf(){
spfa();
while(dijk()){
typ df = INF;
UP(i, 0, iv) h[i] += dis[i];
for(int i=back[it]; i!=EDGE_NIL; i=back[es[i].to]){
df = sd min(df, (typ)es[i^1].lf);
}
for(int i=back[it]; i!=EDGE_NIL; i=back[es[i].to]){
es[i].lf += df;
es[i^1].lf -= df;
}
maxf += df;
minc += df * h[it];
}
}
};// {}}}