POJ Going Home (2195)(最小費用最大流)


Going Home
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 22076   Accepted: 11148

Description

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. 

Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point. 

You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.

Input

There are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of 'H's and 'm's on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.

Output

For each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay.

Sample Input

2 2
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0

Sample Output

2
10
28

Source


題意:有n*m的矩陣,H表示這個點是一個房子,m表示這個點是一個人,現在每一個人需要走入一個房間,已經知道的是認得數目和房子的個數一定是相同的,現在問這些人都回到一個房間所走的總的步數最小


分析:找這些人到這些房子的最小步數,我們可以建一個超級源點和超級匯點,源點到每個人的費用爲0,距離爲1

每個房子到匯點費用爲0,距離爲1,人到房子的距離是1,費用爲座標差的和


//數組開大一些
#include <stdio.h>
#include <string.h>
#include <queue>
#include <stdlib.h>
using namespace std;
#define inf 0x3f3f3f3f
#define N 300
struct node
{
    int u,v,cap,cost,next;

}eg[N*N];
struct node1
{
    int x,y;
}q1[N*N],q2[N*N];
char mp[200][200];
int head[N],vis[N],dis[N],pre[N];
int top;
void add(int u,int v,int cap,int cost)
{
    eg[top].u=u;
    eg[top].v=v;
    eg[top].cap=cap;
    eg[top].cost=cost;
    eg[top].next=head[u];
    head[u]=top++;

    eg[top].u=v;
    eg[top].v=u;
    eg[top].cap=0;
    eg[top].cost=-cost;
    eg[top].next=head[v];
    head[v]=top++;
}
int spfa(int s,int t)
{
    int i,j;
    for(i=1;i<=t;i++)
    {
        dis[i]=inf;
        pre[i]=-1;
        vis[i]=0;
    }
    int q[112345];
    int in=0,out=0;
    q[in++]=s;
    dis[s]=0;
    vis[s]=1;
    while(in>out)
    {
        int u=q[out++];
        vis[u]=0;
        for(i=head[u];i!=-1;i=eg[i].next)
        {
            if(eg[i].cap>0)
            {
                int v=eg[i].v;
                if(dis[v]>dis[u]+eg[i].cost)
                {
                    dis[v]=dis[u]+eg[i].cost;
                    pre[v]=i;   //i指的是以v爲終點這條邊在eg中的編號
                    if(!vis[v])
                    {
                        vis[v]=1;
                        q[in++]=v;
                    }
                }
            }
        }
    }
    if(dis[t]==inf)return 0;
    else return dis[t];
}
int sap(int s,int t)
{
    int i;
    int ans=0,max_flow=0;
    int flow;
    while(spfa(s,t))
    {
        for(i=1;i<=t;i++)
            printf("%d  %d \n",i,pre[i]);
        top=0;
        flow=inf;
        for(i=pre[t];i!=-1;i=pre[eg[i].u])
            if(eg[i].cap<flow)
            flow=eg[i].cap;
        for(i=pre[t];i!=-1;i=pre[eg[i].u])
        {
            eg[i].cap-=flow;
            eg[i^1].cap+=flow;
        }
        ans+=dis[t];
        max_flow+=flow;
    }
    return ans;
}
int main()
{
    int n,m,i,j;
    while(~scanf("%d%d",&n,&m))
    {
        top=0;
        memset(head,-1,sizeof(head));
        int top1=0,top2=0;
        if(n==0&&m==0)
            break;
        for(i=0;i<n;i++)
        {
            scanf("%s",mp[i]);
        }
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                if(mp[i][j]=='m')
                {
                    q1[top1].x=i;
                    q1[top1++].y=j;
                }
                else if(mp[i][j]=='H')
                {
                    q2[top2].x=i;
                    q2[top2++].y=j;
                }
            }
        }
        for(i=0;i<top1;i++)
        {
            add(1,i+2,1,0);
            for(j=0;j<top2;j++)
            {
                int l=abs(q1[i].x-q2[j].x)+abs(q1[i].y-q2[j].y);
                //printf("   %d\n",l);
                add(i+2,top1+j+2,1,l);
            }
        }
        for(j=0;j<top2;j++)
            add(top1+j+2,top1+top2+2,1,0);
        int s=1,t=top1+top2+2;
        printf("%d\n",sap(s,t));



    }
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章