poj2195_GoingHome【最小费用最大流】

这道题的题意是:在一个矩阵空间中,分布着m个人和m个房子,每个房子中要安排一个人,每个人移动一步需要1美元,求为每个人安排房子后所需要的金钱的最小值。
//建立一个原点s,链接人,人和每个房子都要建边,费用为,abs(x人-x房子)+abs(y人-y房子)。
//每个房子链接一个汇点T。
//套用最小费用最大流即可。
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <queue>
#define Maxsize 240
using namespace std;
struct loc{
	int x,y;
}due[Maxsize];
struct Edge{
	int to,cap,cost,rev;
};
vector<Edge> g[Maxsize];
queue<int> que;
char ch[Maxsize][Maxsize];
int dist[Maxsize];
int prev[Maxsize];
int pree[Maxsize];
bool inque[Maxsize];
int n,m;
int sh,sm;
int T;
void add_edge(int from,int to,int cap,int cost)
{
	g[from].push_back((Edge){to,cap,cost,g[to].size()});
	g[to].push_back((Edge){from,0,-cost,g[from].size()-1});
}
int abs(int x)
{
	if(x>0)
		return x;
	return -x;
}
void init()
{
	int i;
	sh=0;sm=0;
	for(i=0;i<Maxsize;i++)
		g[i].clear();
}
void scanf_map()
{
	int i,j,k;
	for(i=0;i<n;i++)
		{
			gets(ch[i]);
			for(j=0;j<m;j++)
			{
				if(ch[i][j]=='H')
				{
					sh++;
					due[sh].x=i;
					due[sh].y=j;
					add_edge(0,sh,1,0);
				}
			}
		}
	for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
			    if(ch[i][j]=='m')
				{
					sm++;
					for(k=1;k<=sh;k++)
					{
						add_edge(k,sh+sm,1,abs(due[k].x-i)+abs(due[k].y-j));
					}
				}
			}
		}
	T=sh+sm+1;
	for(i=sh+1;i<T;i++)
	{
		add_edge(i,T,1,0);
	}
}
int FindMinCostFlow()
{
	int res=0;
	int u,v;
	int f=sh>sm?sm:sh;
	while(f>0)
	{
		//spfa算法求最短路,并记录路径
		memset(dist,0x3f,sizeof(dist));
		memset(inque,0,sizeof(inque));
		dist[0]=0;
		inque[0]=1;
		que.push(0);
		while(!que.empty())
		{
			u=que.front();que.pop();inque[u]=0;
			for(v=0;v<g[u].size();v++)
			{
				Edge &e=g[u][v];
				if(e.cap>0&&dist[e.to]>dist[u]+e.cost)
				{
					dist[e.to]=dist[u]+e.cost;
					prev[e.to]=u;
					pree[e.to]=v;
					if(!inque[e.to])
					{
						que.push(e.to);
						inque[e.to]=1;
					}
				}
			}
			
		}
		//更改路径流量
		for(v=T;v!=0;v=prev[v])
		{
			Edge &e=g[prev[v]][pree[v]];
			e.cap-=1;
			g[e.to][e.rev].cap+=1;
		}
		f-=1;
		res+=dist[T];
	}
	return res;
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		getchar();
		if(n==0&&m==0)
			break;
		init();
		scanf_map();
		printf("%d\n",FindMinCostFlow());
	}
	return 0;
}

你可能感兴趣的:(poj2195_GoingHome【最小费用最大流】)