http://acm.hdu.edu.cn/showproblem.php?pid=1533 #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> using namespace std; #define N 205 #define _M 23000 struct node { int x,y; }H[N],M[N]; int ch,cm; int beg,end; int k; char map[N][N]; struct Graph { struct edge { int v,next,w,flow; edge(){}; edge(int a,int b,int c,int d){ next=a;v=b;w=c;flow=d; } }E[_M]; int head[N]; int dis[N]; bool h[N]; int pre[N]; int path[N]; int NE,NV; void init() { memset(head,-1,sizeof(head)); NE=0; ch=cm=0; NV=205; } void insert(int u,int v,int w,int flow) { E[NE]=edge(head[u],v,w,flow); head[u]=NE++; E[NE]=edge(head[v],u,-w,0); head[v]=NE++; } bool update(int u,int v,int w) { if(dis[u]+w<dis[v]) { dis[v]=dis[u]+w; return true; } return false; } bool spfa() { queue<int> q; q.push(beg); memset(dis,0x3f,sizeof(dis)); memset(pre,-1,sizeof(pre)); memset(h,0,sizeof(h)); dis[beg]=0; while(!q.empty()) { int u=q.front(); q.pop(); h[u]=0; for(int i=head[u];i!=-1;i=E[i].next) { int v=E[i].v; if(E[i].flow>0&&update(u,v,E[i].w)) { pre[v]=u; path[v]=i; if(!h[v]) { h[v]=1; q.push(v); } } } } if(pre[end]==-1) return false; return true; } int mincost_maxflow() { int ans=0; while(spfa()) { int Min=INT_MAX; for(int i=end;i!=beg;i=pre[i]) if(E[path[i]].flow<Min) Min=E[path[i]].flow; for(int i=end;i!=beg;i=pre[i]) { E[path[i]].flow-=Min; E[path[i]^1].flow+=Min; } ans+=dis[end]; } return ans; } }G; int main(void) { int n,m; while(scanf("%d%d",&n,&m),n||m) { k=1; G.init(); for(int i=0;i<n;i++) { scanf("%s",map[i]); for(int j=0;j<m;j++) { if(map[i][j]=='H') { H[ch].x=i; H[ch++].y=j; } else if(map[i][j]=='m') { M[cm].x=i; M[cm++].y=j; } } } beg=0; end=2*ch+1; for(int i=0;i<cm;i++) { G.insert(beg,i+1,0,1); for(int j=0;j<ch;j++) { int temp=abs(H[i].x-M[j].x)+abs(H[i].y-M[j].y); G.insert(i+1,j+1+ch,temp,1); } G.insert(i+1+ch,end,0,1); } printf("%d/n",G.mincost_maxflow()); } } 每次从源点找一条最短路到汇点,然后更新路径容量