HDU 1533

http://acm.hdu.edu.cn/showproblem.php?pid=1533

人和房子数量相同,每个人进房子,费用是人到房子的曼哈顿距离,求最小费用

可用最小费用最大流求解,建立虚拟的源点和汇点即可

#include <iostream>

#include <cstdio>

#include <cstring>

#include <queue>

using namespace std ;

int ABS(int x)

{

    return x>0?x:-x ;

}

struct point{

    int x,y ;

}mm[100005],hh[100005] ;

const int INF=0xfffffff ;

struct node{

    int s,t,cap,cost,nxt ;

}e[200005] ;

int sumflow ;

int n,m,cnt,head[1005],vis[1005],dis[1005],pre[1005] ;

char M[1005][1005] ;

void add(int s,int t,int cap,int cost)

{

    e[cnt].s=s ;e[cnt].t=t ;e[cnt].cap=cap ;e[cnt].cost=cost ;e[cnt].nxt=head[s] ;head[s]=cnt++ ;

    e[cnt].s=t ;e[cnt].t=s ;e[cnt].cap=0 ;e[cnt].cost=-cost ;e[cnt].nxt=head[t] ;head[t]=cnt++ ;

}

int spfa(int s,int t,int N)

{

    for(int i=0 ;i<=N ;i++)

        dis[i]=INF ;

    dis[s]=0 ;

    memset(vis,0,sizeof(vis)) ;

    memset(pre,-1,sizeof(pre)) ;

    vis[s]=1 ;

    queue <int> q ;

    q.push(s) ;

    while(!q.empty())

    {

        int u=q.front() ;

        q.pop() ;

        vis[u]=0 ;

        for(int i=head[u] ;i!=-1 ;i=e[i].nxt)

        {

            int tt=e[i].t ;

            if(e[i].cap && dis[tt]>dis[u]+e[i].cost)

            {

                dis[tt]=dis[u]+e[i].cost ;

                pre[tt]=i ;

                if(!vis[tt])

                {

                    vis[tt]=1 ;

                    q.push(tt) ;

                }

            }

        }

    }

    if(dis[t]==INF)return 0 ;

    return 1 ;

}

int MCMF(int s,int t,int N)

{

    int flow,minflow,mincost ;

    mincost=flow=0 ;

    while(spfa(s,t,N))                                                

    {

        minflow=INF ;

        for(int i=pre[t] ;i!=-1 ;i=pre[e[i].s])

            minflow=min(minflow,e[i].cap) ;

        flow+=minflow ;

        for(int i=pre[t] ;i!=-1 ;i=pre[e[i].s])

        {

            e[i].cap-=minflow ;

            e[i^1].cap+=minflow ;

        }

        mincost+=dis[t]*minflow ;

    }

    sumflow=flow ;//最大流 

    return mincost ;

}

int main()

{

    while(scanf("%d%d",&n,&m))

    {

        if(!n && !m)break ;

        cnt=0 ;

        memset(head,-1,sizeof(head)) ;

        for(int i=0 ;i<n ;i++)

            scanf("%s",M[i]) ;

        int cm,ch ;

        cm=ch=0 ;

        for(int i=0 ;i<n ;i++)

        {

            for(int j=0 ;j<m ;j++)

            {

                if(M[i][j]=='m')

                {

                    mm[cm].x=i ;

                    mm[cm++].y=j ;

                }

                if(M[i][j]=='H')

                {

                    hh[ch].x=i ;

                    hh[ch++].y=j ;

                }

            }

        } 

        int SS=0 ;

        int ST=2*ch+1 ;

        for(int i=0 ;i<ch ;i++)

        {

            add(0,i+1,1,0) ;

            for(int j=0 ;j<ch ;j++)

            {

                int temp=ABS(mm[i].x-hh[j].x)+ABS(mm[i].y-hh[j].y) ;

                add(i+1,j+1+ch,1,temp) ;

            }

            add(i+1+ch,ST,1,0) ;

        }

        printf("%d\n",MCMF(SS,ST,ST+1)) ;

    }

    return 0 ;

}
View Code

 

 

你可能感兴趣的:(HDU)