POJ

题意:每个人到每个房子一一对应,费用为曼哈顿距离,求最小的费用

题解:单源点汇点最小费用最大流,每个人和房子对于建边

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cassert>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;
using namespace __gnu_cxx;

const double g=10.0,eps=1e-7;
const int N=300+10,maxn=10000+10,inf=0x3f3f3f;

struct edge{
    int to,Next,c;
    int cost;
}e[maxn<<2];
int cnt,head[N];
int s,t,ans[N][N];
int dis[N],path[N],pre[N];
void add(int u,int v,int c,int cost)
{
   // cout<<u<<" "<<v<<" "<<c<<" "<<cost<<endl;
    e[cnt].to=v;
    e[cnt].c=c;
    e[cnt].cost=cost;
    e[cnt].Next=head[u];
    head[u]=cnt++;
    e[cnt].to=u;
    e[cnt].c=0;
    e[cnt].cost=-cost;
    e[cnt].Next=head[v];
    head[v]=cnt++;
}
bool spfa()
{
    memset(pre,-1,sizeof pre);
    memset(dis,inf,sizeof dis);
    dis[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=head[x];~i;i=e[i].Next)
        {
            int te=e[i].to;
            if(e[i].c>0&&dis[x]+e[i].cost<dis[te])
            {
                dis[te]=dis[x]+e[i].cost;
                pre[te]=x;
                path[te]=i;
                q.push(te);
            }
        }
    }
    return pre[t]!=-1;
}
int mincostmaxflow()
{
    int cost=0,flow=0;
    while(spfa())
    {
        int f=inf;
        for(int i=t;i!=s;i=pre[i])
            if(f>e[path[i]].c)
                f=e[path[i]].c;
        flow+=f;
        cost+=dis[t]*f;
        for(int i=t;i!=s;i=pre[i])
        {
            e[path[i]].c-=f;
            e[path[i]^1].c+=f;
        }
    }
    return cost;
}
void init()
{
    cnt=0;
    memset(head,-1,sizeof head);
}
int main()
{
   /* ios::sync_with_stdio(false);
    cin.tie(0);*/
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m)break;
        init();
        int house=0,man=0;
        pii ho[N],ma[N];
        for(int i=1;i<=n;++i)
        {
            char a[N];
            scanf("%s",a+1);
            for(int j=1;j<=m;j++)
            {
                if(a[j]=='H')ho[++house]=mp(i,j);
                else if(a[j]=='m')ma[++man]=mp(i,j);
            }
        }
        for(int i=1;i<=house;i++)
        {
            for(int j=1;j<=man;j++)
            {
                int cost=abs(ho[i].fi-ma[j].fi)+abs(ho[i].se-ma[j].se);
            //    cout<<i<<" "<<j<<" "<<cost<<endl;
                add(i,house+j,inf,cost);
               // add(house+j,i,inf,cost);
            }
        }
        s=house+man+1,t=house+man+2;
        for(int i=1;i<=house;i++)add(s,i,1,0);
        for(int i=1;i<=man;i++)add(i+house,t,1,0);
        printf("%d
",mincostmaxflow());
    }
    return 0;
}
/*******************

********************/
View Code
原文地址:https://www.cnblogs.com/acjiumeng/p/7801940.html