题意:
给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致。man每移动一格需花费$1(即单位费用=单位距离),一间house只能入住一个man。现在要求所有的man都入住house,求最小费用。
man可以从house上跨过
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define INF 99999999
int n,m,source,end1,cnt;
int head[11000];
int vis[11000];
int pre[11000];
int dis[11000];
int s,T;
struct w
{
int i,j;
} a[11000],b[11000];
struct node
{
int u,v,w,f,next;
} edge[110000];
void add(int u,int v,int w,int f)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].f=f;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].u=v;
edge[cnt].v=u;
edge[cnt].w=0;
edge[cnt].f=-f;
edge[cnt].next=head[v];
head[v]=cnt++;
}
int SPFA()
{
int i;
memset(pre,-1,sizeof(pre));
memset(vis,0,sizeof(vis));
for(i=0;i<cnt;i++)
dis[i]=INF;
queue<int>q;
dis[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
i=head[u];
vis[u]=0;
while(i!=-1)
{
if(edge[i].w>0&&dis[edge[i].v]>dis[u]+edge[i].f)
{
dis[edge[i].v]=dis[u]+edge[i].f;
pre[edge[i].v]=i;
if(!vis[edge[i].v])
{
vis[edge[i].v]=1;
q.push(edge[i].v);
}
}
i=edge[i].next;
}
}
if(pre[T]==-1)
return 0;
return 1;
}
int MincostMaxFlow()
{
int ans=0;
while(SPFA())
{
int maxl=INF;
int p=pre[T];
while(p!=-1)
{
maxl=min(maxl,edge[p].w);
p=pre[edge[p].u];
}
p=pre[T];
while(p!=-1)
{
edge[p].w-=maxl;
edge[p^1].w+=maxl;
ans+=maxl*edge[p].f;
p=pre[edge[p].u];
}
}
return ans;
}
int main()
{
char g;
while(~scanf("%d %d",&n,&m),n||m)
{
int k=0;
int l=0;
source=0;
cnt=0;
int len;
memset(head,-1,sizeof(head));
for(int i=1; i<=n; i++)
{
getchar();
for(int j=1; j<=m; j++)
{
scanf("%c",&g);
if(g=='H')
{
a[++k].i=i;
a[k].j=j;
}
else if(g=='m')
{
b[++l].i=i;
b[l].j=j;
}
}
}
end1=l+k+1;
for(int i=1; i<=k; i++)
{
add(source,i,1,0);
for(int j=1; j<=l; j++)
{
len=abs(a[i].i-b[j].i)+abs(a[i].j-b[j].j);
add(i,j+k,1,len);
}
}
for(int i=1;i<=l;i++)
{
add(i+k,end1,1,0);
}
s=source;
T=end1;
int suu;
suu=MincostMaxFlow();
printf("%d\n",suu);
}
return 0;
}
就是加一个源点一个汇点然后模版,就是数据处理起来略坑啊,而且这个模版也没有彻底了解,开学再看看吧