1. 程式人生 > >Going Home poj 2195 最小費用最大流

Going Home poj 2195 最小費用最大流

題目大意

給定一個N*M的地圖,地圖上有若干個man和house,且man與house的數量一致。man每移動一格需花費$1(即單位費用=單位距離),一間house只能入住一個man。現在要求所有的man都入住house,求最小費用。

分析

費用流的模板套一下,建圖隨便建。

ps:陣列開小改了我兩個小時。

code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#include<queue>; using namespace std; struct arr{ int x,y,w,c,next; }edge[1000000]; int ls[12000]; int dis[12000]; int f[1000000]; int v[12000]; int sign[12000]; int h[12000][3],mh; int M[12000][3],mm; int edge_m; int ans; int s,t; int n,m; int add(int x,int y,int w,int c) { edge_m++; edge[edge_m]=(arr){x,y,w,c,ls[x]},f[edge_m]=w,ls[x]=edge_m; edge_m++; edge[edge_m]=(arr){y,x,w,-c,ls[y]},f[edge_m]=0
,ls[y]=edge_m; } bool bfs() { for (int i=s;i<=t+1;i++) dis[i]=2000000000; memset(v,0,sizeof(v)); queue<int> q; dis[s]=0; v[s]=0; q.push(s); do { int x=q.front(); q.pop(); for (int i=ls[x];i;i=edge[i].next) { if ((dis[edge[i].y]>dis[x]+edge[i].c)&&(f[i])) { dis[edge[i].y]=dis[x]+edge[i].c; sign[edge[i].y]=i; if
(!v[edge[i].y]) { v[edge[i].y]=1; q.push(edge[i].y); } } } v[x]=0; }while (!q.empty()); if (dis[t]!=2000000000) return true; else return false; } void mcf() { int mn=2000000000; int x=t; while (sign[x]) { mn=min(mn,f[sign[x]]); x=edge[sign[x]].x; } ans+=mn*dis[t]; x=t; while (sign[x]) { f[sign[x]]-=mn; f[sign[x]^1]+=mn; x=edge[sign[x]].x; } } int dinic() { while (bfs()) { mcf(); } } int main() { scanf("%d%d",&n,&m); while(n && m) { edge_m=1; memset(edge,0,sizeof(edge)); memset(ls,0,sizeof(ls)); memset(f,0,sizeof(f)); memset(sign,0,sizeof(sign)); mm=0; mh=0; for (int i=1;i<=n;i++) { getchar(); for (int j=1;j<=m;j++) { char c; scanf("%c",&c); if (c=='m') { mm++; M[mm][1]=i; M[mm][2]=j; } if (c=='H') { mh++; h[mh][1]=i; h[mh][2]=j; } } } s=0; t=mm+mh+1; for (int i=1;i<=mm;i++) for (int j=1;j<=mh;j++) add(i,mm+j,1,abs(M[i][1]-h[j][1])+abs(M[i][2]-h[j][2])); for (int i=1;i<=mm;i++) add(s,i,1,0); for (int i=1;i<=mh;i++) add(mm+i,t,1,0); ans=0; dinic(); printf("%d\n",ans); scanf("%d%d",&n,&m); } return 0; }