最小费用流模板(压入重标记)

这份模板还是保持我在博客中用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;
}

posted @ 2011-08-21 10:29  Lxsec  阅读(959)  评论(0编辑  收藏  举报