题意:给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致。man每移动一格需花费$1,一间house只能入住一个man。现在要求所有的man都入住house,求最小费用。
思路:明显的最小费用最大流,源点为0,每个人为一个点连源点,容量为1,边权(费用)为0,每个人连每一间房子,容量为1,边权为两者坐标之差的和,然后房子和汇点连边,容量为1,边权为0即可,非常简单的建图和思路,然后跑一遍最小费用最大流就可以了。
Trick:这么简单的水题我居然超时了快十次,一开始以为是我用string数组来处理输入超时,改用了char数组,还是超时,就不懂了....甚至怀疑模板敲错了..又敲了一次..还是TLE..最后折腾了一晚上,最后我把初始化时候将按照输入的n初始化改成了统计的人的数目来初始化,80多MS就过了...gg...题目不是给了n最多不是也才100么..表示懵逼...
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <cstdlib> #include <algorithm> #include <vector> #include <map> #include <string> #include <set> #include <ctime> #include <cmath> #include <cctype> using namespace std; #define maxn 220 #define LL long long int cas=1,T; const int INF = 1e9; struct Edge { int from,to,cap,flow,cost; Edge(){} Edge(int u,int v,int c,int f,int co):from(u),to(v),cap(c),flow(f),cost(co){} }; int n,m; int num1,num2; struct MCMF { int s,t; vector<Edge>edges; vector<int>G[maxn]; int inq[maxn]; //是否在队列中 int d[maxn]; int p[maxn]; //上一条弧 int a[maxn]; //可改进量 void init() { for (int i = 0;i<=num1*2+1;i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap,int cost) { edges.push_back(Edge(from,to,cap,0,cost)); edges.push_back(Edge(to,from,0,0,-cost)); int mm = edges.size(); G[from].push_back(mm-2); G[to].push_back(mm-1); } bool BellmanFord(int &flow,int &cost) { for (int i = 0;i<=2*num1+1;i++) d[i]=INF; memset(inq,0,sizeof(inq)); d[s]=0; inq[s]=1; p[s]=0; a[s]=INF; queue<int>q; q.push(s); while (!q.empty()) { int u = q.front();q.pop(); inq[u]=0; for (int i = 0;i<G[u].size();i++) { Edge &e = edges[G[u][i]]; if (e.cap > e.flow && d[e.to]>d[u]+e.cost) { d[e.to]=d[u]+e.cost; p[e.to]=G[u][i]; a[e.to]=min(a[u],e.cap-e.flow); if (!inq[e.to]) { q.push(e.to); inq[e.to]=1; } } } } if (d[t]==INF) return false; //s-t不连通,失败退出 flow+=a[t]; cost+=d[t]*a[t]; int u = t; while (u!=s) { edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; u=edges[p[u]].from; } return true; } int Mincost(int s,int t) { this->s=s; this->t=t; int flow = 0; int cost = 0; while (BellmanFord(flow,cost)); return cost; } }mc; string mapp[120]; //char mapp[120][120]; struct peo { int x,y; }p[120]; struct hou { int x,y; }h[120]; int main() { while (scanf("%d%d",&n,&m)==2 && n) { int house = 0; int peo = 0; int hpos = 0; int peopos = 0; for (int i = 0;i<n;i++) cin >> mapp[i]; for (int i = 0;i<n;i++) for (int j = 0;j<m;j++) { if (mapp[i][j] == 'm') { peo++; p[peopos].x=i; p[peopos++].y=j; } if (mapp[i][j] == 'H') { house++; h[hpos].x=i; h[hpos++].y=j; } } num1 = peo; mc.init(); for (int i = 0;i<peo;i++) { mc.AddEdge(0,i+1,1,0); mc.AddEdge(i+peo+1,peo*2+1,1,0); for (int j = 0;j<house;j++) { mc.AddEdge(i+1,peo+1+j,1,(abs(p[i].x-h[j].x)+abs(p[i].y-h[j].y))); } } printf("%d\n",mc.Mincost(0,2*peo+1)); } return 0; }