zoj 2404 最小费用流
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2404
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <vector> #define maxn 550 #define maxe 100000 #define INF 0x3f3f3f using namespace std; struct Edge{ int from,to,cap,flow,cost; int next; void assign(int a,int b,int c,int d,int e,int f){ from = a; to = b; cap = c; flow = d; cost = e; next = f; } }; struct MCMF{ int n,cnt; int head[maxn]; int d[maxn]; Edge edges[maxe]; int inq[maxn]; int p[maxn]; int res[maxn]; void init(int n){ this->n = n; cnt = 0; memset(head,-1,sizeof(head)); } void addedge(int a,int b,int c,int d,int e){ edges[cnt].assign(a,b,c,d,e,head[a]); head[a] = cnt++; edges[cnt].assign(b,a,0,0,-e,head[b]); head[b] = cnt++; } bool SPFA(int s,int t,int &flow,int& cost){ memset(d,0x3f,sizeof(d)); memset(inq,0,sizeof(inq)); d[s] = 0; inq[s] = 1; p[s] = s; res[s] = INF; res[t] = 0; queue<int> Q; Q.push(s); while(!Q.empty()){ int u = Q.front(); Q.pop(); inq[u] = 0; for(int i=head[u];i!=-1;i=edges[i].next){ Edge& e = edges[i]; if(e.cap > e.flow && d[e.to] > d[e.from] + e.cost){ d[e.to] = d[e.from] + e.cost; p[e.to] = i; res[e.to] = min(res[u],e.cap - e.flow); if(!inq[e.to]){ Q.push(e.to); inq[e.to] = 1; } } } } if(res[t] == 0) return false; flow += res[t]; cost += d[t]*res[t]; for(int i=t;i!=s;i=edges[p[i]].from){ edges[p[i]].flow += res[t]; edges[p[i]^1].flow -= res[t]; } return true; } }solver; int Mincost(int s,int t){ int flow = 0, cost = 0; while(solver.SPFA(s,t,flow,cost)){} return cost; } int main() { //freopen("input.txt","r",stdin); int N,M; while(cin>>N>>M && N+M){ int ltail = 0; int rtail = 0; struct node{ int x, y; }l[maxn],r[maxn]; char ch[105]; for(int i=1;i<=N;i++){ scanf("%s",ch); for(int j=0;j<M;j++){ if(ch[j] == 'H'){ r[rtail].x = i; r[rtail++].y = j; } else if(ch[j] == 'm'){ l[ltail].x = i; l[ltail++].y = j; } } } int n = ltail + rtail; solver.init(n); int s = 0, t = n+1; for(int i=0;i<ltail;i++) solver.addedge(s,i+1,1,0,0); for(int i=0;i<rtail;i++) solver.addedge(i+1+ltail,t,1,0,0); for(int i=0;i<ltail;i++) for(int j=0;j<rtail;j++){ int cost = (int)abs(1.0*l[i].x-1.0*r[j].x) + (int)abs(1.0*l[i].y-1.0*r[j].y); solver.addedge(i+1,ltail+1+j,1,0,cost); } printf("%d\n",Mincost(s,t)); } }