POJ - 2195 Going Home (费用流 水)

POJ - 2195

题意:这道题题意还是很清晰的

思路:这个连边就更清晰了....

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cmath>
using namespace std;

const int maxn = 200 + 10, maxe = maxn*maxn,inf = 0x3f3f3f3f;
struct node
{
    int from,to,next;
    int cap,w,rev;
    node(){}
    node(int a,int b,int c,int d,int e,int f):
        from(a),to(b),next(c),cap(d),w(e),rev(f){}
}edge[maxe << 1];
int edgenum,mnum,hnum;
int h[maxn],man[maxn][3],house[maxn][2],pre[maxn],a[maxn],d[maxn],inq[maxn];
int st,t;
void init()
{
    memset(man,-1,sizeof(man));
    memset(house,-1,sizeof(house));
    for(int i = 0; i < maxn; i++)
        h[i] = -1,pre[i] = 0;
    mnum = edgenum = hnum = 0;
}
void add(int u,int v,int cap,int w)
{
    edge[edgenum] = node(u,v,h[u],cap,w,edgenum+1);h[u] = edgenum++;
    edge[edgenum] = node(v,u,h[v],0,-w,edgenum-1); h[v] = edgenum++;
}
char s[120];
void build()    //建图部分
{
    for(int i = 1; i <= mnum; i++)  add(st,i,1,0);
    for(int j = 1; j <= hnum; j++)  add(j+mnum,t,1,0);

    for(int i = 1; i <= mnum; i++)
    for(int j = 1; j <= hnum; j++)
    {
        int w = abs(house[j][0] - man[i][0]) + abs(house[j][1] - man[i][1]);
        add(i,j+mnum,1,w);
    }
}
int bfs(int num)
{
    for(int i = 0; i < maxn; i++)
        d[i] = inf,a[i] = 0,inq[i] = 0;
    queue<int> q;
    q.push(0);
    d[0] = 0;a[0] = inf;
    inq[0] = 1;
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        inq[u] = 0;
        for(int i = h[u]; ~i; i = edge[i].next)
        {
            int v = edge[i].to,cap = edge[i].cap, w = edge[i].w;
            if(cap && d[v] > d[u] + w)
            {
                a[v] = min(a[u],cap);
                d[v] = d[u] + w;
                pre[v] = i;
                if(!inq[v]) {q.push(v); inq[v] = 1;}
            }
        }
    }
    if(d[t] == inf ) return 0;
    for(int u = t; u != st; u = edge[pre[u]].from)
    {
        int rev = edge[pre[u]].rev;
        edge[pre[u]].cap -= a[t];
        edge[rev].cap += a[t];
    }
    return d[t];
}
void solve()
{
    int res = 0;
    int i = 0;
    while(int k = bfs(i++))
        res += k;
    printf("%d\n",res);
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m) && n+m)
    {
        init();
        for(int i = 0; i < n ; i++)
        {
            scanf("%s",s);
            for(int j = 0; j < m ; j++)
            {
                if(s[j] == 'm')
                {
                    int id  = ++mnum;
                    man[id][0] = i, man[id][1] = j;
                }
                else if(s[j] == 'H')
                {
                    int id = ++hnum;
                    house[id][0] = i, house[id][1] = j;
                }
            }
        }
        st = 0, t = mnum+hnum+1;
        build();
        solve();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值