摘自大神:
https://blog.csdn.net/jzq233jzq/article/details/73123089
源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。
Edmond-Karp经过修改
很像dinic
正着走spfa(SLF优化)
上代码:
int n, m, s, t; struct edge { int to, w, nx, cost; } e[N << 1]; int fi[N]; int ce = 1; int dis[N]; bool vis[N]; int cur[N]; int ans = 0; inline void add(int u, int v, int w, int c) { e[++ce] = edge{v, w, fi[u], c}; fi[u] = ce; } int spfa() { me(vis, 0); me(dis, 0x3f); deque<int> q; q.push_back(s); vis[s] = 1; dis[s] = 0; while (!q.empty()) { int u = q.front(); q.pop_front(); for (int i = fi[u]; ~i; i = e[i].nx) { int v = e[i].to; if (e[i].w && dis[u] + e[i].cost < dis[v]) { dis[v] = dis[u] + e[i].cost; if (!vis[v]) { vis[v] = 1; if (!q.empty() && dis[v] < dis[q.front()]) q.push_front(v); else q.push_back(v); } } } vis[u] = 0; } return dis[t] < inf; } int dfs(int u, int flow) { if (u == t) { vis[u] = 1; return flow; } int used = 0; vis[u] = 1; for (int &i = cur[u]; ~i; i = e[i].nx) { int v = e[i].to; if ((!vis[v]||v==t) && e[i].w && dis[u] + e[i].cost == dis[v]) { int di = dfs(v, min(e[i].w, flow - used)); if (di) e[i].w -= di, e[i ^ 1].w += di, ans += e[i].cost * di, used += di; if (used == flow) break; } } return used; } int costflow(int s, int t) { int res = 0; while (spfa()) { vis[t] = 1; For(i, 1, n) cur[i] = fi[i]; while (vis[t]) { me(vis, 0); res += dfs(s, inf); } } return res; } int main() { #ifndef ONLINE_JUDGE file("test"); #endif me(fi, -1); sdf(n), sdf(m), sdf(s), sdf(t); while (m--) { int u, v, w, c; sdf(u), sdf(v), sdf(w), sdf(c); add(u, v, w, c), add(v, u, 0, -c); } int res = costflow(s, t); printf("%d %d", res, ans); return 0; }