题意:最小费用最大流模版,在最大流的基础上加上费用,要求流最大的同时费用最小
思路:在EK的基础上将bfs换成spfa,每次求出最短路,在求出的最短路的基础上求最大流,若边的费用为cost,则反向边的费用为-cost
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 5005;
const int inf = 0x3f3f3f3f;
int m, n, s, t, vis[maxn], flow[maxn], dis[maxn], N;
struct edge {
int rev, to, c, w;
edge(int rev = 0, int to = 0, int c = 0, int w = 0) : rev(rev), to(to), c(c), w(w) {}
};
struct node {
int id, pre;
node(int id = 0, int pre = 0) : id(id), pre(pre) {}
}path[maxn];
vector<edge> g[maxn];
void addedge(int u, int v, int c, int w)
{
g[u].push_back(edge(g[v].size(), v, c, w));
g[v].push_back(edge(g[u].size()-1, u, 0, -w));
}
int spfa(int s, int t)
{
memset(dis, inf, sizeof(dis));
memset(vis, 0, sizeof(vis));
memset(flow, inf, sizeof(flow));
queue<int> q;
q.push(s); dis[s] = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
vis[u] = 0;
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i].to, di = g[u][i].w, c = g[u][i].c;
if (c && dis[v] > dis[u] + di) {
dis[v] = dis[u] + di;
path[v].id = i;
path[v].pre = u;
flow[v] = min(flow[u], c);
if (!vis[v]) {
q.push(v);
vis[v] = 1;
}
}
}
}
return flow[t] != flow[s];
}
void solve(int s, int t)
{
int maxflow = 0, mincost = 0, id, now, pre;
while (spfa(s, t)) {
maxflow += flow[t];
mincost += flow[t]*dis[t];
now = t;
while (now != s) {
pre = path[now].pre, id = path[now].id;
edge &e = g[pre][id];
e.c -= flow[t];
g[e.to][e.rev].c += flow[t];
now = pre;
}
}
printf("%d %d\n", maxflow, mincost);
}
int main()
{
while (cin >> n) {
cin >> m >> s >> t;
for (int i = 0; i < m; i++) {
int u, v, w, f;
cin >> u >> v >> w >> f;
addedge(u, v, w, f);
}
solve(s, t);
}
return 0;
}