最小费用流模板(压入重标记)
这份模板还是保持我在博客中用Dinic的习惯,模板和Dinic的写法非常相近,所以看过我其他随笔的人应该能看得懂这份模板。
代码挺简单的。SPFA找最短路。本模板我拿去做poj 3422题目了,所以里面写的是最大流最大费用,不过有相应注解,可以灵活运用。
#include <stdio.h> #include <stdlib.h> #include <iostream> #define M 200001 #define maxx 2000 #define Max(a, b) a > b ? a : b #define Min(a, b) a < b ? a : b #define inf 0xffffff struct T { int from, to, val; int next, cost; }edge[M]; int len; int visit[M], pre[M], dist[M], que[M], vis[M], pos[M], map[100][100]; void init() { memset(vis,-1,sizeof(vis)); len=0; } void add(int from, int to, int val, int cost) { edge[len].from = from,edge[len].to = to, edge[len].val = val, edge[len].cost = cost; edge[len].next = vis[from], vis[from] = len++; edge[len].from = to, edge[len].to = from, edge[len].val = 0, edge[len].cost = -cost; edge[len].next = vis[to], vis[to] = len++; } int SPFA(int s, int t, int n) { int i, to, k; for (i = 0; i <= n; i++) { pre[i] = -1, visit[i] = 0; } int head, tail; head = tail = 0; for (i = 0; i <= n; i++) dist[i] = -1;//求最小费用时这里得改成正无穷 que[tail++] = s, pre[s] = s, dist[s] = 0, visit[s] = 1; while (head != tail) { int from = que[head++]; visit[from] = 0; for (k = vis[from]; k != -1; k = edge[k].next) { to = edge[k].to; if (edge[k].val > 0 && dist[from]+edge[k].cost > dist[to])//最大费用,求最小费用时这里的改符号 { dist[to] = dist[from] + edge[k].cost; pre[to] = from; pos[to] = k; if (!visit[to]) { visit[to] = 1; que[tail++] = to; } } } } if (pre[t] != -1 && dist[t] > -1)//求最小费用时这里改成dit[t] < 正无穷 return 1; return 0; } int MinCostFlow(int s, int t, int n) { if (s == t) { //这里具体情况具体分析,如果有附加s跟t就不用,如果用数据中的点作为s跟t就得考虑 //直接返回某个值。否则SPFA里的队列会死循环。 } int flow = 0, cost = 0; while (SPFA(s, t, n)) { int from, min = inf; for (from = t; from != s; from = pre[from]) min = Min(min, edge[pos[from]].val); flow += min; cost += dist[t] * min; for (from = t; from != s; from = pre[from]) { edge[pos[from]].val -= min; edge[pos[from]^1].val += min; } } return cost; } int main() { int n,m,i,j,s,t,ans,x,num; while (scanf("%d%d", &n, &m)!=EOF) { init(); for (i = 0; i < n; i++) for (j = 0; j < n; j++) scanf("%d", &map[i][j]); num = n * n; for (i = 0; i < n; i++) for (j = 0; j < n; j++) { x = i * n + j; add(x, x + num, 1, map[i][j]); add(x, x + num, inf, 0); if (i + 1 < n) add(x + num, x + n, inf, 0); if (j + 1 < n) add(x + num, x + 1, inf, 0); } s = 2 * n * n, t = s + 1, n = t + 1; add(s, 0, m, 0); add(s - 1, t, m, 0); ans = MinCostFlow(s, t, t + 1); printf("%d\n", ans); } return 0; }