建图很简单
bfs预处理地图,距离就为费用
源点到所有m建边,流量1费用0
m到所有H建边,流量1费用为距离
H到所有汇点建边,流量1费用0
#include<cstdio> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define MAXN 10005 #define MAXM 1000000 #define INF 0x3f3f3f3 #define getid(x,y) x*m+y int dx[]={-1,1,0,0}; int dy[]={0,0,-1,1}; struct node { int u,v,f,c,next; }e[MAXM]; int n,m,head[MAXN],pre[MAXN],dist[MAXN],vis[MAXN],ans; bool use[105][105]; int en,s,t,maxflow,mincost; //s源点,t汇点 void add(int u,int v,int c,int f)//加边 { e[en].u=u; e[en].v=v; e[en].c=c; e[en].f=f; e[en].next=head[u]; head[u]=en++; e[en].u=v; e[en].v=u; e[en].c=-c; e[en].f=0; e[en].next=head[v]; head[v]=en++; } int spfa() { int i,u,v; for(i=0;i<=t;i++) pre[i]=-1,vis[i]=0,dist[i]=INF; dist[s]=0; vis[s]=1; queue<int>q; q.push(s); while(!q.empty()) { u=q.front(); q.pop(); for(i=head[u];i!=-1;i=e[i].next) { v=e[i].v; if(e[i].f>0&&dist[u]+e[i].c<dist[v]) { dist[v]=dist[u]+e[i].c; pre[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } vis[u]=0; } if(dist[t]==INF) return 0; return 1; } void add() { int v; int maxf=INF; for(v=pre[t];~v;v=pre[e[v].u]) maxf=min(maxf,e[v].f); for(v=pre[t];~v;v=pre[e[v].u]) { e[v].f-=maxf; e[v^1].f+=maxf; mincost+=e[v].c; } maxflow+=maxf; } struct pp { int x,y,dis; pp(int a,int b) {x=a;y=b;dis=0;} }; struct orz { int id; int w; orz(int a,int b) {id=a;w=b;} }; vector<orz> gg[10005]; void init() { maxflow=0; mincost=0; en=0; s=n*m; t=n*m+1; memset(head,-1,sizeof(head)); for(int i=0;i<t;i++) gg[i].clear(); } char mp[105][105]; bool isok(int x,int y) { return x>=0&&x<n&&y>=0&&y<m&&!use[x][y]; } void bfs(pp t) { pp save=t; queue<pp> Q; Q.push(t); memset(use,0,sizeof(use)); while(!Q.empty()) { pp f=Q.front();Q.pop(); for(int d=0;d<4;d++) { t.x=f.x+dx[d]; t.y=f.y+dy[d]; t.dis=f.dis+1; if(isok(t.x,t.y)) { use[t.x][t.y]=1; Q.push(t); if(mp[t.x][t.y]=='H') { gg[getid(save.x,save.y)].push_back( orz(getid(t.x,t.y),t.dis) ); } } } } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; init(); vector<pp> v; for(int i=0;i<n;i++) { scanf("%s",mp[i]); for(int j=0;j<m;j++) { if(mp[i][j]=='m') { v.push_back(pp(i,j)); add(s,getid(i,j),0,1); } else if(mp[i][j]=='H') { add(getid(i,j),t,0,1); } } } for(int i=0;i<v.size();i++) { bfs(v[i]); int m_id=getid(v[i].x,v[i].y); for(int j=0;j<gg[m_id].size();j++) { int h_id=gg[m_id][j].id; int dis=gg[m_id][j].w; add(m_id,h_id,dis,INF); } } while(spfa()) add(); printf("%d\n",mincost); } return 0; }