P3381 【模板】最小费用最大流
学到了MCMF(min cost max flow),学到了EK算法。
我其实不会EK,只会死记dinic,事实证明EK算法非常的浅显易懂。
EK算法是怎么弄的?
说白了就是一个bfs找增广路径,只要有流量可以流,就去增广一波。
如果探到了t点的话,就可以进行一次成功的增广了。
如何实现?
我们需要两个辅助数组,比dinic多。
-
flow数组,表示一个点目前可以流的流量。
-
last数组,表示终边为这个点的边的下标。
-
fa数组,表示一个点的父结点,直至源点。
发现EK算法去更新答案减流量的时候,不像dinic那样用dfs做,而是一个循环解决。
如何使用循环解决?就利用上面的三个数组。
MCMF问题,只需要在EK的做法上,用spfa代替那个bfs。
如同一位dalao说的:EK算法的主体就是spfa或者bfs。更新操作不过是辅助而已。
使用spfa,可以求最短路径。在这里,用来求最小费用。
在最小费用上,如果能增广,就增广。最终得到的就是最小费用前提下的最大流。
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
const int maxn = 5005, maxm = 50005, INF = 0x3f3f3f3f;
struct Edges
{
int next, to, weight, cost;
} e[maxm << 1];
int head[maxn], tot = 1;
int n, m, s, t;
int maxflow, mincost;
int dist[maxn];
bool vis[maxn];
int fa[maxn];
int flow[maxn];
int last[maxn];
int read()
{
int ans = 0, s = 1;
char ch = getchar();
while(ch > '9' || ch < '0')
{
if(ch == '-') s = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
ans = ans * 10 + ch - '0';
ch = getchar();
}
return s * ans;
}
void link(int u, int v, int w, int c)
{
e[++tot] = (Edges){head[u], v, w, c};
head[u] = tot;
}
void addEdges(int u, int v, int w, int c)
{
link(u, v, w, c);
link(v, u, 0, -c);
}
bool spfa()
{
memset(dist, 0x3f, sizeof(dist));
memset(flow, 0x3f, sizeof(flow));
memset(fa, 0, sizeof(fa));
std::queue<int> q;
dist[s] = 0;
q.push(s); vis[s] = true;
while(!q.empty())
{
int u = q.front(); q.pop(); vis[u] = false;
for(int i = head[u]; i; i = e[i].next)
{
int v = e[i].to;
if(e[i].weight > 0 && dist[u] + e[i].cost < dist[v])
{
dist[v] = dist[u] + e[i].cost;
fa[v] = u;
last[v] = i;
flow[v] = std::min(flow[u], e[i].weight);
if(!vis[v])
{
q.push(v); vis[v] = true;
}
}
}
}
return dist[t] != INF;
}
void update()
{
maxflow += flow[t];
mincost += flow[t] * dist[t];
for(int i = t; i != s; i = fa[i])
{
e[last[i]].weight -= flow[t];
e[last[i] ^ 1].weight += flow[t];
}
}
void ek()
{
while(spfa()) update();
}
int main()
{
n = read(), m = read(), s = read(), t = read();
while(m--)
{
int u = read(), v = read(), w = read(), c = read();
addEdges(u, v, w, c);
}
ek();
printf("%d %d\n", maxflow, mincost);
return 0;
}

浙公网安备 33010602011771号