luogu P3381【模板】最小費用最大流
阿新 • • 發佈:2018-11-23
嘟嘟嘟
沒錯,我開始學費用流了!
做法也是比較樸素的\(spfa\)。
就是每一次以費用為權值跑一遍\(spfa\)找到一條最短路,然後把這條道全流滿,並把這一次的流量和費用累加到答案上。因此我們需要記錄路徑。
就這樣一直跑直到沒有增廣路為止,然後好像就沒了。(不難啊……)
因為每一隻找一條道,所以其實挺慢的。
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<stack> #include<queue> using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a, x) memset(a, x, sizeof(a)) #define rg register typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 5e3 + 5; const int maxm = 5e4 + 5; inline ll read() { ll ans = 0; char ch = getchar(), last = ' '; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(last == '-') ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0'); } int n, m, s, t; struct Edge { int nxt, from, to, cap, c; }e[maxm << 1]; int head[maxn], ecnt = -1; void addEdge(int x, int y, int w, int f) { e[++ecnt] = (Edge){head[x], x, y, w, f}; head[x] = ecnt; e[++ecnt] = (Edge){head[y], y, x, 0, -f}; head[y] = ecnt; } queue<int> q; int dis[maxn], flow[maxn], pre[maxn]; bool in[maxn]; bool spfa(int s, int t) { Mem(dis, 0x3f); Mem(in, 0); dis[s] = 0; in[s] = 1; flow[s] = INF; //源點流量無限,故初值為INF q.push(s); while(!q.empty()) { int now = q.front(); q.pop(); in[now] = 0; for(int i = head[now], v; i != -1; i = e[i].nxt) { v = e[i].to; if(e[i].cap > 0 && dis[now] + e[i].c < dis[v]) { dis[v] = dis[now] + e[i].c; flow[v] = min(flow[now], e[i].cap); pre[v] = i; if(!in[v]) in[v] = 1, q.push(v); } } } return dis[t] != INF; } int maxFlow = 0, minCost = 0; void update(int s, int t) { int x = t; while(x != s) { int i = pre[x]; e[i].cap -= flow[t]; e[i ^ 1].cap += flow[t]; x = e[i].from; } maxFlow += flow[t]; minCost += flow[t] * dis[t]; } void MCMF(int s, int t) { while(spfa(s, t)) update(s, t); } int main() { Mem(head, -1); n = read(); m = read(); s = read(); t = read(); for(int i = 1; i <= m; ++i) { int x = read(), y = read(), w = read(), f = read(); addEdge(x, y, w, f); } MCMF(s, t); write(maxFlow), space, write(minCost), enter; return 0; }