Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 23603 | Accepted: 11885 |
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
这道题 真心把我给弄得没脾气了, 刚学会 最小费用流,
先讲一下我认知的最小费用流:
最大流(Dinic算法)与最小费用流(SPFA)的区别与共同之处 :
1: 区别: 最大流一般不会用到 u(起点) 费用流需要用到 u(起点) 在遍历寻找短板时从汇点往回找;
2: 区别: 最大流只需要用到cap 容量即可, 而最小费用流 牵扯到费用的问题,所以会有cost 费用问题;
正因为因为费用的问题,最小费用流可以用类似最短路SPFA的算法去找最短增广路;
3: 相似 : 都需要 构建图, 构建源点与汇点, 其实所有的问题都在构建图上;
因为不知道 哪个房子到人是最短的, 所以每个房子都要 与每个人建边, 费用是 x+y 坐标轴距离
然后 房子与源点, 人与汇点建立 边 构成 一个完整的图;
注意! 注意! 注意! 注意!
我就是死在这上面一晚上, 因为我直接上的头文件,所以开的数组是1e6+5
然后就一直TLE TLE 一直调啊调 就是 TLE, 没办法, 最后 要了 别人的AC代码,把我的代码 一部分一部分拷贝过去;
AC,AC 依然AC , mmp 最后才想到是不是数组的问题呢,我把数组改成 5e5 然后就神奇的AC了 时间是700ms
我又把数组改成1e5 后 立即变成140ms 这效率 0.0
代码: 可以拿去做模板 嘿嘿
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <math.h>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
#define S1(n) scanf("%d",&n)
#define SL1(n) scanf("%I64d",&n)
#define S2(n,m) scanf("%d%d",&n,&m)
#define SL2(n,m) scanf("%I64d%I64d",&n,&m)
#define Pr(n) printf("%d\n",n)
using namespace std;
typedef long long ll;
const double PI=acos(-1);
const int INF=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=100000;
const int MOD=1e9+7;
const int mod=1e9+7;
int dir[5][2]={0,1,0,-1,1,0,-1,0};
struct node{
int u,v,w,c,next;
}edge[maxn];
struct mp{
int x,y,z;
}mpa[maxn],mpb[maxn];
int n,m;
int head[maxn],start,END,cnt,sum;
int dis[maxn],pre[maxn],vis[maxn];
void init()
{
cnt=0;
mem(head,-1);
}
int ffabs(int x,int y)
{
return fabs(x)+fabs(y);
}
void add(int u,int v,int c,int w)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].c=c;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
// 有向图, 反射边 cost = -cost
edge[cnt].u=v;
edge[cnt].v=u;
edge[cnt].w=-w;
edge[cnt].c=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
int SPFA()
{
queue<int>Q;
mem(pre,-1);
mem(vis,0);
mem(dis,INF);
dis[start]=0;
vis[start]=1;
Q.push(start);
while(!Q.empty())
{
int t=Q.front();
Q.pop();
vis[t]=0;
for(int i=head[t];i!=-1;i=edge[i].next)//
{
int t1= edge[i].v;//下一个点
int t2= edge[i].w;// 费用
if(edge[i].c&&dis[t1]>dis[t]+t2)// 最短路
{
dis[t1]=dis[t]+t2;
pre[t1]=i;
if(!vis[t1])
{
Q.push(t1);
vis[t1]=1;
}
}
}
}
if(dis[END]==INF)return 0;
return 1;
}
int MCMF()
{
int minflow=0;
int mincost=0;
while(SPFA())
{
minflow=INF;
for(int i=pre[END];i!=-1;i=pre[edge[i].u])
{
minflow=min(minflow,edge[i].c);
}
for(int i=pre[END];i!=-1;i=pre[edge[i].u])
{
edge[i].c-=minflow;
edge[i^1].c+=minflow;
}
mincost+=dis[END];
}
return mincost;
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
if(n==0&&m==0)
break;
init();
mem(mpa,0);
mem(mpb,0);
char str[120];
start=0;END=n*m+1;
int num=1;
int k=0,h=0;
for(int i=1;i<=n;i++)
{
scanf("%s",str+1);
for(int j=1;j<=strlen(str);j++)
{
if(str[j]=='H')
{
mpa[++k].x=i;
mpa[k].y=j;
mpa[k].z=num;
add(start,num,1,0);
num++;
}
if(str[j]=='m')
{
mpb[++h].x=i;
mpb[h].y=j;
mpb[h].z=num;
add(num,END,1,0);
num++;
}
}
}
for(int i=1;i<=k;i++)
{
for(int j=1;j<=h;j++)
{
int w=ffabs(mpa[i].x-mpb[j].x,mpa[i].y-mpb[j].y);
add(mpa[i].z,mpb[j].z,1,w);
}
}
int ans=MCMF();
Pr(ans);
}
return 0;
}
123