Going Home
Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point.
You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.
InputThere are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of 'H's and 'm's on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.
OutputFor each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay.
Sample Input
2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0
Sample Output
2 10 28
给你一张图,图上有若干个人和若干个屋子,现在要使的这若干个人都进到屋子里,并且一个屋子只能进一个人,求总步数最小。
思路:图转边 建图(超级源点和汇点)跑最小费用最大流板子即可
#include<bits/stdc++.h> #define FIN freopen("input.txt","r",stdin) #define ll long long #define mod 1000000007 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define inf 0x3f3f3f3f const int maxn = 50005; using namespace std; int s,t,cnt=1,n,m; char str[205][205]; int head[maxn],Next[maxn],To[maxn],ct[maxn],flow[maxn],dis[maxn],vis[maxn],pre[maxn],id[maxn]; struct node{ int x; int y; }p[maxn]; void add(int u,int v,int w,int cost){ Next[++cnt]=head[u]; head[u]=cnt; To[cnt]=v; flow[cnt]=w; ct[cnt]=cost; } void get_graph(){ s=0; t=0; int hh=0,mm=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(str[i][j]=='H'){ hh++; p[hh].x=i; p[hh].y=j; } } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(str[i][j]=='m'){ mm++; add(s,mm+hh,1,0); add(mm+hh,s,0,0); for(int k=1;k<=hh;k++){ add(mm+hh,k,1,abs(i-p[k].x)+abs(j-p[k].y)); add(k,mm+hh,0,-abs(i-p[k].x)-abs(j-p[k].y)); } } } } t=hh+mm+1; for(int i=1;i<=hh;i++){ add(i,t,1,0); add(t,i,0,0); } } bool spfa(){ memset(vis,0,sizeof(vis)); memset(dis,inf,sizeof(dis)); memset(pre,-1,sizeof(pre)); dis[s]=0; queue<int> q; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];~i;i=Next[i]){ int v=To[i]; int d=ct[i]; if(dis[v]>dis[u]+d&&flow[i]>0){ dis[v]=dis[u]+d; pre[v]=u; id[v]=i; if(!vis[v]){ vis[v]=1; q.push(v); } } } } return dis[t]<inf; } int Maxflow(){ int ans=0; while(spfa()){ int Min=inf; for(int i=t;i!=s;i=pre[i]){ Min=min(flow[id[i]],Min); } for(int i=t;i!=s;i=pre[i]){ flow[id[i]]-=Min; flow[id[i]^1]+=Min; } ans+=dis[t]; } return ans; } int main() { #ifndef ONLINE_JUDGE FIN; #endif while(~scanf("%d %d",&n,&m),n+m){ for(int i=1;i<=n;i++) scanf("%s",str[i]+1); memset(head,-1,sizeof(head)); cnt=1; get_graph(); printf("%d\n",Maxflow()); } return 0; }