最小费用最大流
求出一条最小费用边,然后对这条边增广,重复上述过程,直到没有到汇点的边
求最小费用边,用spfa()
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define cin(a) scanf("%d",&a)
#define pii pair<int,int>
#define ll long long
#define gcd __gcd
const int inf = 0x3f3f3f3f;
const int maxn = 200100;
const int M = 1e9+7;
int n,m,s,t;
struct node
{
int to,cost,dis,next;
}a[maxn];
int head[maxn],cnt = 2;
void add(int u,int v,int w,int f)
{
a[cnt].to = v;a[cnt].cost = w;a[cnt].dis = f;
a[cnt].next = head[u];head[u] = cnt;cnt++;
}
int dis[maxn];
bool vis[maxn];
int pre[maxn]; //前驱
int incf[maxn]; //当前路上的最小流
bool spfa()
{
mem(dis,inf);mem(vis,0);
dis[s] = 0;incf[s] = inf;
queue<int> q;q.push(s);
while(!q.empty())
{
int u = q.front();q.pop();vis[u] = 0;
for(int i = head[u];i; i = a[i].next)
{
if(!a[i].cost) continue;
int v = a[i].to;
if(dis[v] > dis[u]+a[i].dis)
{
dis[v] = dis[u]+a[i].dis;
incf[v] = min(incf[u],a[i].cost);
pre[v] = i;
if(!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
if(dis[t] < inf) return 1;
return 0;
}
int maxflow,mincost;
void mcff()
{
while (spfa())
{
maxflow += incf[t];
mincost += dis[t]*incf[t];
int x = t;
while(x != s)
{
int i = pre[x];
a[i].cost -= incf[t];
a[i^1].cost += incf[t];
x = a[i^1].to;
}
}
}
例题
https://www.luogu.com.cn/problem/P3381