| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 23975 | Accepted: 12034 |
Description
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.
Input
Output
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
Source
[Submit] [Go Back] [Status] [Discuss]
题意:给出一个图,m代表人,h代表房子,一间房子只能住一个人,格子之间距离都为1,问所有人走到房子最短距离是多少;
思路:可以把距离看成费用,这题就是最小费用流问题,房子代表汇点,人代表源点;
建图:点与点之间建边,费用为1,容量无限;
超级源点s连向m,容量1,费用0;
h连向超级汇点t,容量1,费用0;
反向边费用相反;
AC code:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <queue>
#include <vector>
#include <stack>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 20000+50;
const int MAXE = MAXN*4;
const int INF = 0x3f3f3f3f;
struct node {
int u,v,w;
int cap,next;
} edge[MAXE] ;
int pre[MAXN];
int Head[MAXN];
int Dis[MAXN];
bool vis[MAXN];
int n,m,top;
void Init(){
memset(Head,-1,sizeof(Head));
top=0;
}
void AddEdge(int u,int v,int w,int cap) {
edge[top].u=u; edge[top].v=v;
edge[top].w=w; edge[top].cap=cap;
edge[top].next=Head[u];
Head[u] = top++;
edge[top].u=v; edge[top].v=u;
edge[top].w=-w; edge[top].cap=0;
edge[top].next=Head[v];
Head[v]=top++;
}
int SPFA(int s,int t) {
stack<int> Q;
memset(Dis,INF,sizeof Dis);
memset(vis,false,sizeof vis);
memset(pre,-1,sizeof pre);
Dis[s] = 0 ; vis[s]=true;
Q.push(s);
while(!Q.empty()) {
int u = Q.top(); Q.pop();
for(int i = Head[u]; i!=-1; i = edge[i].next) {
int v = edge[i].v;
if(edge[i].cap && Dis[v]>Dis[u]+edge[i].w) {
Dis[v] = Dis[u]+edge[i].w;
pre[v]=i;
if(!vis[v]) {
vis[v]=true;
Q.push(v);
}
}
}
vis[u] = false;
}
if(Dis[t]==INF) return 0;
else return 1;
}
int MCF(int s,int t){
int MinFlow,MinCost=0;
while(SPFA(s,t)){
MinFlow=INF;
for(int k=pre[t];k!=-1;k=pre[edge[k].u]){
MinFlow=min(MinFlow,edge[k].cap);
}
for(int k=pre[t];k!=-1;k=pre[edge[k].u]){
edge[k].cap-=MinFlow;
edge[k^1].cap+=MinFlow;
}
MinCost+=Dis[t]*MinFlow;
}
return MinCost;
}
int getIndex(int i,int j){
return i*m+j;
}
int ok(int i,int j){
if(i>=0&&i<n&&j>=0&&j<m) return 1;
else return 0;
}
char map[200][200];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int main() {
while(~scanf("%d%d",&n,&m)){
if(n==0&&m==0) break;
for(int i=0;i<n;i++){
scanf("%s",&map[i]);
}
int s=n*m+1,t=n*m+2;
Init();
for(int i=0;i<n;i++){
//printf("%s\n",map[i]);
for(int j=0;j<m;j++){
if(map[i][j]=='m') AddEdge(s,getIndex(i,j),0,1);
else if(map[i][j]=='H') AddEdge(getIndex(i,j),t,0,1);
for(int k=0;k<4;k++){
int x=i+dx[k];
int y=j+dy[k];
if(ok(x,y)) AddEdge(getIndex(i,j),getIndex(x,y),1,INF);
}
}
}
int ans=MCF(s,t);
printf("%d\n",ans );
}
return 0;
}
741



被折叠的 条评论
为什么被折叠?



