pku 2195 Going Home 最小费最大流问题

http://poj.org/problem?id=2195

题意是:有相同数量的人与房子,每一时刻人都可以花费1$的钱走一步,问让每个人到达一个屋子的最少需要的费用。

建立源点与汇点,求有源点到汇点的最小费用最大流;改了一下不需要f[][]的模板。

#include <iostream>

#include <cstring>

#include <cstdio>

#include <queue>

#include <cstdlib>

#define maxn 207

using namespace std;



const int inf = 999999999;



struct node

{

    int x,y;

}p[maxn],h[maxn];

int c[maxn][maxn],f[maxn][maxn],w[maxn][maxn];

int pre[maxn],dis[maxn];

int n,m,pn,hn,s,t;

char str[maxn][maxn];

bool inq[maxn];

int ans;



int Abs(int x)

{

    return x > 0 ? x : -x;

}

void spfa()

{

    int v;

    queue<int>q;

    for (int i = 0; i < maxn; ++i)

    {

        dis[i] = inf; pre[i] = -1;

        inq[i] = false;

    }

    q.push(s); inq[s] = true; dis[s] = 0;

    while (!q.empty())

    {

        int u = q.front(); q.pop();

        inq[u] = false;

        for (v = 0; v <= t; ++v)

        {

            if (c[u][v]&& dis[v] > dis[u] + w[u][v])

            {

                dis[v] = dis[u] + w[u][v];

                pre[v] = u;

                if (!inq[v])

                {

                    q.push(v);

                    inq[v] = true;

                }

            }

        }

    }

}

void mcmf()

{

    while (1)

    {

        spfa();

        if (pre[t] == -1) break;

        int x = t,minf = inf;

        while (pre[x] != -1)

        {

            minf = min(minf,c[pre[x]][x]);

            x = pre[x];

        }

        x = t;

        while (pre[x] != -1)

        {

            c[pre[x]][x] -= minf;

            c[x][pre[x]] += minf;

            ans += minf*w[pre[x]][x];

            x = pre[x];

        }

    }

}

int main()

{

    //freopen("in.txt","r",stdin);

    int i,j,pn,hn;

    while (~scanf("%d%d",&n,&m))

    {

        if (!n && !m) break;

        pn = hn = 0;

        for (i = 0; i < n; ++i)

        {

            scanf("%s",str[i]);

            for (j = 0; j < m; ++j)

            {

                if (str[i][j] == 'H')

                {

                    h[++hn].x = i; h[hn].y = j;

                }

                else if (str[i][j] == 'm')

                {

                    p[++pn].x = i; p[pn].y = j;

                }

            }

        }

        memset(c,0,sizeof(c));

        memset(f,0,sizeof(f));

        memset(w,0,sizeof(w));

        s = 0; t = pn + hn + 1;

        for (i = 1; i <= pn; ++i) c[s][i] = 1;

        for (i = 1; i <= hn; ++i) c[i + pn][t] = 1;

        for (i = 1; i <= pn; ++i)

        {

            for (j = 1; j <= hn; ++j)

            {

                c[i][j + pn] = 1;

                w[i][j + pn] = Abs(p[i].x - h[j].x) + Abs(p[i].y - h[j].y);

                w[j + pn][i] = -w[i][j + pn];

            }



        }

        ans = 0;

        mcmf();

        printf("%d\n",ans);

    }

    return 0;

}

  

你可能感兴趣的:(home)