裸的最小费用流,当然也可以用KM算法解决,但是比较难写。
注意反向边的距离为正向边的相反数(因此要用SPFA)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=302,src=301,sink=300,INF=1e+8;
int n,m,man,house,x[maxn],y[maxn],cap[maxn][maxn],w[maxn][maxn];
vector<int> next[maxn];
void addedge(int a,int b)
{
next[a].push_back(b);next[b].push_back(a);
cap[a][b]=1;cap[b][a]=0;
}
int ab(int xx)
{
if(xx<0)return xx*(-1);
else return xx;
}
int fa[maxn];
int len(int a,int b)
{
if((a==src)||(a==sink)||(b==src)||(b==sink))return 0;
return ab(x[b]-x[a])+ab(y[b]-y[a]);
}
bool inq[maxn];
int times[maxn],dist[maxn];
bool SPFA()
{
memset(inq,0,sizeof(inq));
for(int i=0;i<maxn;i++)
dist[i]=INF;
dist[src]=0;
queue<int>q;
q.push(src);
inq[src]=true;
while(!q.empty())
{
int now=q.front();
q.pop();
inq[now]=false;
for(int i=0;i<next[now].size();i++)
{
int np=next[now][i];
if((dist[np]>dist[now]+w[now][np])&&cap[now][np]>0)
{
dist[np]=dist[now]+w[now][np];
fa[np]=now;
if(!inq[np]){q.push(np);inq[np]=true;}
}
}
}
if( dist[sink]<INF)return true;
else return false;
}
int augment()
{
int u=sink,delta=INF;
while(u!=src)
{
if(cap[fa[u]][u]<delta)delta=cap[fa[u]][u];
u=fa[u];
}
u=sink;
while(u!=src)
{
cap[fa[u]][u]-=delta;
cap[u][fa[u]]+=delta;
u=fa[u];
}
return dist[sink]*delta;
}
int main()
{ios::sync_with_stdio(false);
while(cin>>n>>m)
{
if(n==0&&m==0)return 0;
man=0;house=150;
memset(cap,0,sizeof(cap));memset(w,0,sizeof(w));
for(int i=0;i<maxn;i++)
while(next[i].size()>0)next[i].pop_back();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
char c;
cin>>c;
if(c==‘m‘)
{
x[man]=i;y[man]=j;
man++;
}
if(c==‘H‘)
{
x[house]=i;y[house]=j;
house++;
}
}
}
for(int i=150;i<house;i++)
{
addedge(i,sink);
for(int j=0;j<man;j++)
addedge(j,i);
}
for(int j=0;j<man;j++) addedge(src,j);
int ans=0;
for(int i=0;i<man;i++)
for(int j=150;j<house;j++)
{
w[i][j]=len(i,j);
w[j][i]=w[i][j]*(-1);
}
while(SPFA())
{
ans+=augment();
}
cout<<ans<<endl;
}
return 0;
}
,没什么别的了,很简单。
原文:http://www.cnblogs.com/heisenberg-/p/6442095.html