poj2195Going Home最小费用流

来源:互联网 发布:广告机发布软件 编辑:程序博客网 时间:2024/06/02 06:20

On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step he moves, until he enters a house. The task is complicated with the restriction that each house can accommodate only one little man.
网址http://poj.org/problem?id=2195
man的数量加上house的数量值为超级源点编号,超级源点编号加一为超级汇点编号。

#include<iostream>#include<queue>#include<string>#include<algorithm>#include<cmath>using namespace std;#define INF 0x3f3f3f3f#define MAX 200+5#define N 5000+5#define mem(arr,a) memset(arr,a,sizeof(arr))int cost[MAX][MAX];int cap[MAX][MAX];char maps[MAX][MAX];int d[N];int vis[N];int pre[N];int mincost;int chouse, cman;int num;int row, col;struct place {    int x, y;};place house[N], man[N];int dis(place a, place b){    return abs(a.x - b.x) + abs(a.y - b.y);}void input(){    mincost = 0;    chouse = cman = 0;    num = 0;    for (int i = 0; i < row; i++){        for (int j = 0; j < col; j++){            cin >> maps[i][j];            if (maps[i][j] == 'm'){                num++;                man[cman].x = i, man[cman].y = j;                cman++;            }            else if (maps[i][j] == 'H'){                house[chouse].x = i, house[chouse].y = j;                chouse++;            }        }    }}void build(){    mem(cost, 0);    mem(cap, 0);    mem(pre, -1);    for (int i = 0; i < num; i++){        for (int j = 0; j < num; j++){            cost[i][j + num] = dis(man[i], house[j]);            cost[j + num][i] = -cost[i][j + num];            cap[i][j + num] = 1;        }        cap[num * 2][i] = 1;        cap[i + num][num * 2 + 1] = 1;        cost[num * 2][i] = 0;        cost[i + num][num * 2 + 1] = 0;    }}bool spfa(){    fill(d, d + num * 2 + 2, INF);    fill(vis, vis + num * 2 + 2, 0);    queue<int>q;    q.push(num * 2);    d[num * 2] = 0;    while (!q.empty()){        int u = q.front(); q.pop();        vis[u] = 0;        for (int i = 0; i < num * 2 + 2; i++){            if (cap[u][i]>0 && d[i] > d[u] + cost[u][i]){                d[i] = d[u] + cost[u][i];                pre[i] = u;                if (!vis[i]){                    vis[i] = 1;                    q.push(i);                }            }        }    }    if (d[num * 2 + 1] != INF)return true;    return false;}void add(){    for (int i = num * 2 + 1; pre[i] != -1; i = pre[i]){        cap[pre[i]][i] -= 1;        cap[i][pre[i]] += 1;    }    mincost += d[num * 2 + 1];}int solve(){    input();    build();    while (spfa())add();    return mincost;}int main(){    while (cin >> row >> col){        if (!row&&!col)break;        cout << solve() << endl;    }}
原创粉丝点击