#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector> //poj2195最小费用最大流(spfa、EK算法及(构图----尤其重要))
#define inf 1<<30
#define N 210
using namespace std; //构图时,要建立超级源点和超级汇点,源点u都会和每个人相连,cost[u][x]=0, cap[u][x]=1, 每个房子都会和汇点e相连,cost[x][e]=0, cap[x][e]=1
int mantot, houtot, p[N], dis[N], vis[N], cap[N][N], cost[N][N]; //cap表示容量, cost表示花费, 最小费用相当于最短路,最大流相当于每个人对应于一个房子
queue<int> q;
struct node
{
int x, y;
}man[N], hou[N];
int fab(int x)
{
if(x>=0)return x;
else return -x;
}
int step(int a, int b)
{
return fab(man[a].x-hou[b].x)+fab(man[a].y-hou[b].y);
}
void buildmap()
{
int t, j;
for(t=0; t<mantot; ++t) //建立超级源点0, 超级汇点1,其他节点从2开始
{
cap[0][t+2]=1;
cost[0][t+2]=0;
}
for(t=0; t<houtot; ++t) //建立超级汇点
{
cap[t+2+mantot][1]=1;
cost[t+2+mantot][1]=0;
}
for(j=0; j<mantot; j++) //建立人和房子之间的距离,连接起来
{
for(t=0; t<houtot; ++t)
{
cap[j+2][t+2+mantot]=1;
cost[j+2][t+2+mantot]=step(j, t);
cost[t+2+mantot][j+2]=-cost[j+2][t+2+mantot];//注意逆边一定要记得加
}
}
return ;
}
int mpmf()
{
int s=0, e=1, t, g=mantot+houtot+2, u, f=0, totprice=0, flow;
while(!q.empty())
q.pop();
while(1)
{
for(t=0; t<g; ++t)
{
dis[t]=inf;
vis[t]=0;
}
dis[s]=0;
q.push(s);
vis[s]=1;
while(!q.empty()) //spfa算法
{
u=q.front();
q.pop();
vis[u]=0;
for(t=0; t<g; ++t)
{
if(cap[u][t]&&dis[t]>dis[u]+cost[u][t])
{
dis[t]=dis[u]+cost[u][t];
p[t]=u;
if(!vis[t])
{
vis[t]=1;
q.push(t);
}
}
}
}
if(dis[1]==inf) //已经达到最大流且是最小费用
break;
for(t=1, flow=inf; t!=0; t=p[t]) //寻找最小流量
{
if(cap[p[t]][t]<flow)
flow=cap[p[t]][t];
}
for(t=1; t!=0; t=p[t])
{
cap[p[t]][t]-=flow;
cap[t][p[t]]+=flow;
}
f+=flow;
totprice+=flow*dis[1];
}
return totprice;
}
int main()
{
int n, m, t, j;
char a[N][N];
while(scanf("%d%d", &n, &m)!=EOF)
{
if(n==0||m==0)break;
for(t=0; t<n; ++t)
scanf("%s", &a[t]);
mantot=houtot=0; //人的总数,房子的总数
memset(cap, 0, sizeof(cap));//注意!!! 初始化,0表示没有办法到达
for(j=0; j<n; ++j)
{
for(t=0; t<m; ++t)
{
if(a[j][t]=='H')
{
hou[houtot].x=j;
hou[houtot++].y=t;
}
else if(a[j][t]=='m')
{
man[mantot].x=j;
man[mantot++].y=t;
}
}
}
buildmap(); //建图
printf("%d\n", mpmf()); //minpricemaxflow最小费用最大流
}
return 0;
}
最小费用最大流(spfa、EK算法及(构图----尤其重要))
最新推荐文章于 2020-10-02 11:28:57 发布