POJ 2195 Going Home【最小费用最大流】

题意: 给你一个图

 HH. .m
 . . . . .
 . . . . .
 . . . . .
 mm. .H

m代表人 H 代表房子,一个人只能进一个房子,问你如何安排人进房,使得总步数最小。

分析:  可以用最小费用最大流,也可以用二分图最有匹配。

最小费用最大流
#include<stdio.h>
#include<string.h>
#define min(a,b)(a)<(b)?(a):(b)
#define inf 0x1f1f1f
int ab(int x){  return x>0?  x:-x;}
int cap[500][500];
int cost[500][500];
int q[10000];
int pre[500];
int dis[500];
int v[500];
char g[500][500];
int s,t;
int n,m;
int tot=0;
struct node
{
     int x,y;
}h[500],p[500];
int spfa()
{
    int i,x,front,rear;
    front=rear=0;
    for(i=0;i<=t;i++)
        dis[i]=inf;
    memset(v,0,sizeof(v));
    q[rear++]=s;
    dis[s]=0;
    v[s]=1;
    while(front<rear)
    {
        x=q[front++];
        v[x]=0;
        for(i=0;i<=t;i++)
        {
            if(cap[x][i]&&dis[i]>dis[x]+cost[x][i])
            {
                dis[i]=dis[x]+cost[x][i];
                pre[i]=x;
                if(!v[i])
                {
                    v[i]=1;
                    if(dis[i]<=dis[x]&&front>0)
                        q[--front]=i;
                    else 
                    q[rear++]=i;
                }
            }
        }
    }
    if(dis[t]!=inf)
        return 1;
    return 0;
}
int costflow()
{
    int tot=0;
    int flow=0;
    int u;
    int minf=inf;
    while(spfa())
    {
        for(u=t;u!=s;u=pre[u])
        minf=min(minf,cap[pre[u]][u]);
        for(u=t;u!=s;u=pre[u])
        {
            cap[pre[u]][u]-=minf;
            cap[u][pre[u]]+=minf;
            flow+=cost[pre[u]][u]*minf;
        }
    }
    return flow; 
}
int main()
{
    int i,j,pn,hn;
    while(scanf("%d%d",&n,&m),n||m)
    {
        memset(cap,0,sizeof(cap));
        memset(cost,0,sizeof(cost));
        hn=1;pn=1;
        for(i=1;i<=n;i++)
        {
            scanf("%s",g[i]);
            for(j=0;j<m;j++)
                if(g[i][j]=='m'){
                    p[pn].x=i;
                    p[pn++].y=j;
                }
                else if(g[i][j]=='H'){
                    h[hn].x=i;
                    h[hn++].y=j;
                }
        }
        s=0;
        hn--;
        pn--;
        t=pn*2+1;
        for(i=1;i<=pn;i++)
        {
            cap[s][i]=1;
            cost[s][i]=0;
        }
        for(i=pn+1;i<t;i++)
        {
            cap[i][t]=1;
            cost[i][t]=0;
        }
        for(i=1;i<=pn;i++)
            for(j=1;j<=hn;j++)
            {
                cap[i][j+pn]=1;
                cost[i][j+pn]=ab(p[i].x-h[j].x)+ab(p[i].y-h[j].y);
                cost[j+pn][i]-=cost[i][j+pn];
            }
        printf("%d\n",costflow());
    }
    return 0;
}

 

posted @ 2012-05-19 12:36  'wind  阅读(261)  评论(0)    收藏  举报