最小增广路算法
/*
最小费用最大流算法
注释部分是当固定流量K,则在增广时当flow+a>=k时只增广k-flow单位
亦可连一条新汇点到原汇点容量为k,费用为0的边
*/
struct Edge{
int from, to, cap, flow, cost;
Edge(int a, int b, int c, int d, int e) : from(a), to(b), cap(c), flow(d), cost(e){}
};
int k;
struct MCMF{
int n, m, s, t;
vector edges;
VI G[maxn];
bool vis[maxn];
int d[maxn], p[maxn], a[maxn];
void init(int n)
{
this-> n = n;
REP(i, n + 1)
G[i].clear();
edges.clear();
}
void add(int from, int to, int cap, int cost)
{
Edge e(from, to, cap, 0, cost);
edges.PB(e);
Edge e2(to, from, 0, 0, -cost);
edges.PB(e2);
int sz = edges.size();
G[from].PB(sz - 2);
G[to].PB(sz - 1);
}
bool spfa(int s, int t, int& flow, int& cost)
{
queue Q;
CLR(vis, false);
REP(i, n + 1)
d[i] = INF;
d[s] = 0, vis[s] = 1,p[s] = 0, a[s] = INF;
Q.push(s);
while (!Q.empty())
{
int u = Q.front(); Q.pop();
vis[u] = 0;
REP(i, SZ(G[u]))
{
Edge &e = edges[G[u][i]];
if (e.cap > e.flow && d[e.to] > d[u] + e.cost)
{
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u], e.cap - e.flow);
if (!vis[e.to])
{
Q.push(e.to);
vis[e.to] = 1;
}
}
}
}
if (d[t] == INF) return false;
// if (flow + a[t] >= k)
// a[t] = k - flow;
flow += a[t];
cost += d[t] * a[t];
// if (a[t] == 0) return 0;
int u = t;
while (u != s)
{
edges[p[u]].flow += a[t];
edges[p[u] ^ 1].flow -= a[t];
u = edges[p[u]].from;
}
return true;
}
int mincost(int s, int t)
{
int flow = 0, cost = 0;
while (spfa(s, t, flow, cost));
// if (flow >= k)
// break;
if (flow < k) return -1;
return cost;
}}mcmf;
int main()
{
int u, v, a, c;
int n, m;
while (~RIII(n, m, k))
{
mcmf.init(n);
REP(i, m)
{
RIV(u, v, a, c);
FE(j, 1, c)
mcmf.add(u, v, 1, (2 * j - 1) * a);
}
WI(mcmf.mincost(1, n));
}
}
ZKW费用流
struct ZKW_flow{
int st, ed, ecnt, n;
int head[MAXN];
int cap[MAXE], cost[MAXE], to[MAXE], next[MAXE], dis[MAXN]; ;
void init(){
memset(head, 0, sizeof(head));
ecnt = 2;
}
void addEdge(int u, int v, int cc, int ww){
cap[ecnt] = cc; cost[ecnt] = ww; to[ecnt] = v;
next[ecnt] = head[u]; head[u] = ecnt++;
cap[ecnt] = 0; cost[ecnt] = -ww; to[ecnt] = u;
next[ecnt] = head[v]; head[v] = ecnt++;
}
void SPFA(){
for(int i = 1; i <= n; ++i) dis[i] = INF;
priority_queue > Q;
dis[st] = 0;
Q.push(make_pair(0, st));
while(!Q.empty()){
int u = Q.top().second, d = -Q.top().first;
Q.pop();
if(dis[u] != d) continue;
for(int p = head[u]; p; p = next[p]){
int &v = to[p];
if(cap[p] && dis[v] > d + cost[p]){
dis[v] = d + cost[p];
Q.push(make_pair(-dis[v], v));
}
}
}
for(int i = 1; i <= n; ++i) dis[i] = dis[ed] - dis[i];
}
int minCost, maxFlow;
bool use[MAXN];
int add_flow(int u, int flow){
if(u == ed){
maxFlow += flow;
minCost += dis[st] * flow;
return flow;
}
use[u] = true;
int now = flow;
for(int p = head[u]; p; p = next[p]){
int &v = to[p];
if(cap[p] && !use[v] && dis[u] == dis[v] + cost[p]){
int tmp = add_flow(v, min(now, cap[p]));
cap[p] -= tmp;
cap[p^1] += tmp;
now -= tmp;
if(!now) break;
}
}
return flow - now;
}
bool modify_label(){
int d = INF;
for(int u = 1; u <= n; ++u) if(use[u])
for(int p = head[u]; p; p = next[p]){
int &v = to[p];
if(cap[p] && !use[v]) d = min(d, dis[v] + cost[p] - dis[u]);
}
if(d == INF) return false;
for(int i = 1; i <= n; ++i) if(use[i]) dis[i] += d;
return true;
}
int min_cost_flow(int ss, int tt, int nn){
st = ss, ed = tt, n = nn;
minCost = maxFlow = 0;
SPFA();
while(true){
while(true){
for(int i = 1; i <= n; ++i) use[i] = 0;
if(!add_flow(st, INF)) break;
}
if(!modify_label()) break;
}
return minCost;
}
};