poj 2195

9 篇文章 0 订阅
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <vector>
#define MAXN 210
#define MAXE 30010
#define FOR(i_,a,b) for( int i_ = a; i_ <= b; i_ ++ )
#define INF 0x7ffffff
using namespace std;
struct Node
{
    int x;
    int y;
} M[MAXN], H[MAXN];
struct EDGE
{
    int u, v,next;
    int flow, cost, cap ;
}e[MAXE];
int head[MAXN];
int dis_road( int a, int b )
{
    return abs(M[a].x-H[b].x)+abs(M[a].y-H[b].y);
}

void add_edge( int u, int v, int cap, int cost, int &num )
{
    e[num].u = u;
    e[num].v = v;
    e[num].cap = cap;
    e[num].flow = 0;
    e[num].cost = cost;
    e[num].next = head[u];
    head[u] = num ++;

    e[num].u = v;
    e[num].v = u;
    e[num].flow = 0;
    e[num].cap = 0;
    e[num].cost = -cost;
    e[num].next = head[v];
    head[v] = num ++;
}

int get_map( int m, int n )
{
    char map[110];
    int num = 0, mn = 0, hn = 0;
    FOR(i,0,m-1) {
        scanf("%s",map);
        FOR(j,0,n-1){
            if( map[j] =='H' ) H[++hn].x = i, H[hn].y = j;
            if( map[j] == 'm' )M[++mn].x = i, M[mn].y = j;
        }
    }
    FOR(i,0,MAXN )head[i] = -1;
    int s = 0, t = hn*2+1;
    FOR(i,1,mn) {
        add_edge( s,i, 1, 0, num );
        add_edge( mn+i, t, 1, 0, num );
        FOR(j,1,hn) add_edge( i, j+mn, 1, dis_road(i,j), num );
    }
    return t;
}
int d[MAXN],path[MAXN], c[MAXN], que[MAXN];
bool iq[MAXN];
bool spfa( int s, int t, int n )
{
    int front = 0, rear = 0;
    FOR(i,0,n ) d[i] = INF, iq[i] = false;
    d[s]= 0;
    c[s] = INF;
    path[s] = s;
    iq[s] = true;
    que[rear++] = s;
    while(rear!=front)
    {
        int u = que[front++];
        if( front == MAXN ) front = 0;
        iq[u] = false;
        for( int p = head[u]; p!=-1; p = e[p].next )
            if( e[p].cap > e[p].flow && d[ e[p].v ] > d[ u ] + e[p].cost )
            {
                d[ e[p].v ] = d[u] + e[p].cost;
                c[ e[p].v ] = min( c[u], e[p].cap - e[p].flow );
                path[ e[p].v ] = p;
                if( !iq[ e[p].v ] )
                {
                    iq[ e[p].v] = true;
                    que[rear++] = e[p].v;
                    if( rear == MAXN ) rear = 0;
                }
            }
    }
    if( d[t] == INF ) return false;
    else return true;
}
int mincost( int s, int t, int n )
{
    int flow = 0, cost = 0;
    while( spfa( s, t, n ) )
    {
        flow += c[t];
        cost += c[t]*d[t];
        for( int u = t; u!=s; u = e[ path[u] ].u )
        {
            e[ path[u] ].flow += c[t];
            e[ path[u]^1 ].flow -= c[t];
        }
    }
    return cost;
}
int main()
{
    //freopen("in.txt","r", stdin );
    int m, n;
    while( ~scanf("%d%d",&m,&n), m+n )
    {
        int t = get_map( m, n );
        printf("%d\n",mincost(0,t, t+1));
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值