题目链接:
http://poj.org/problem?id=2195
题解:
最小费用流
代码:
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof(a))
const int maxn = 200+10;
struct node
{
int to,next;
int flow,cost;
}edge[maxn*maxn];
int head[maxn],pre[maxn],path[maxn];
int dis[maxn];
int top;
int s,t;
vector<pair<int,int> >hh,mm;
char mp[maxn][maxn];
void init()
{
met(head,-1);
top=0;
}
inline void Add(int u,int v,int w,int cost)
{
edge[top].to=v;
edge[top].flow=w;
edge[top].cost=cost;
edge[top].next=head[u];
head[u]=top++;
}
inline void Add_Edge(int u,int v,int w,int cost)
{
Add(u,v,w,cost);
Add(v,u,0,-cost);
}
int spfa()
{
queue<int>q;
met(dis,inf);
met(pre,-1);
dis[s]=0;
q.push(s);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i!=-1;i=edge[i].next)
{
int y=edge[i].to;
if(edge[i].flow&&dis[y]>dis[x]+edge[i].cost)
{
dis[y]=dis[x]+edge[i].cost;
pre[y]=x;
path[y]=i;
q.push(y);
}
}
}
return pre[t]!=-1;
}
int MIN_FLOW()
{
int cost=0;
int max_flow=0;
while(spfa())
{
int flow=inf;
for(int i=t;i!=s;i=pre[i])
flow=min(flow,edge[path[i]].flow);
for(int i=t;i!=s;i=pre[i])
{
int j=path[i];
edge[j].flow-=flow;
edge[j^1].flow+=flow;
}
max_flow+=flow;
cost+=flow*dis[t];
}
return cost;
}
inline int distance(int x1,int y1,int x2,int y2)
{
return abs(x1-x2)+abs(y1-y2);
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)&&n+m)
{
hh.clear(),mm.clear();
for(int i=1;i<=n;i++)
{
getchar();
for(int j=1;j<=m;j++)
{
scanf("%c",&mp[i][j]);
if(mp[i][j]=='m')
mm.push_back(make_pair(i,j));
if(mp[i][j]=='H')
hh.push_back(make_pair(i,j));
}
}
int h_len=(int)hh.size();
int m_len=(int)mm.size();
s=0,t=h_len+m_len+1;
init();
for(int i=1;i<=h_len;i++)
Add_Edge(s,i,1,0);
for(int i=0;i<h_len;i++)
for(int j=0;j<m_len;j++)
{
int cost=distance(hh[i].first,hh[i].second,mm[j].first,mm[j].second);
Add_Edge(i+1,j+h_len+1,1,cost);
}
for(int i=1;i<=m_len;i++)
Add_Edge(i+h_len,t,1,0);
printf("%d\n",MIN_FLOW());
}
}