poj2195

题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少。

分析:最小费用最大流每个人一个点,每个房子一个点,每个人到所有房子加容量为1费用为二者距离的边,源到所有人加容量为1费用为0的边,所有房子到汇加容量为1费用为0的边。因为没有初始化ne,wa了两次。渐渐开始理解网络流的题型了,是一种可以自由分配,求最优分配方案的题。

View Code
#include < iostream >
#include
< cstdlib >
#include
< cstring >
#include
< cstdio >
#include
< cmath >
using namespace std;

#define inf 0x3f3f3f3f
#define N 205
#define E 40000

struct XPoint
{
int x, y;
}house[N], man[N];

int n, m;
int hcount, mcount;

struct network
{
int nv, ne, pnt[E], nxt[E];
int vis[N], que[N], head[N], pv[N], pe[N];
int flow, cap[E];
int cost, dis[E], d[N];
int src, sink;
void addedge( int u, int v, int c, int w)
{
pnt[ne]
= v;
cap[ne]
= c;
dis[ne]
= + w;
nxt[ne]
= head[u];
head[u]
= (ne ++ );
pnt[ne]
= u;
cap[ne]
= 0 ;
dis[ne]
= - w;
nxt[ne]
= head[v];
head[v]
= (ne ++ );
}
int mincost()
{
int i, k, f, r;
int mxf;
for (flow = 0 , cost = 0 ;;)
{
memset(pv,
- 1 , sizeof (pv));
memset(vis,
0 , sizeof (vis));
for (i = 0 ; i < nv; ++ i)
d[i]
= inf;
d[src]
= 0 ;
pv[src]
= src;
vis[src]
= 1 ;

for (f = 0 , r = 1 , que[ 0 ] = src; r != f;)
{
i
= que[f ++ ];
vis[i]
= 0 ;
if (N == f)
f
= 0 ;
for (k = head[i]; k != - 1 ; k = nxt[k])
if (cap[k] && dis[k] + d[i] < d[pnt[k]])
{
d[pnt[k]]
= dis[k] + d[i];
if ( 0 == vis[pnt[k]])
{
vis[pnt[k]]
= 1 ;
que[r
++ ] = pnt[k];
if (N == r)
r
= 0 ;
}
pv[pnt[k]]
= i;
pe[pnt[k]]
= k;
}
}
if ( - 1 == pv[sink])
break ;
for (k = sink, mxf = inf; k != src; k = pv[k])
if (cap[pe[k]] < mxf)
mxf
= cap[pe[k]];
flow
+= mxf;
cost
+= d[sink] * mxf;
for (k = sink; k != src; k = pv[k])
{
cap[pe[k]]
-= mxf;
cap[pe[k]
^ 1 ] += mxf;
}
}
return cost;
}
void build()
{
hcount
= mcount = 0 ;
for ( int i = 0 ; i < n; i ++ )
{
for ( int j = 0 ; j < m; j ++ )
{
char ch = getchar();
if (ch == ' H ' )
{
house[hcount].x
= i;
house[hcount].y
= j;
hcount
++ ;
}
if (ch == ' m ' )
{
man[mcount].x
= i;
man[mcount].y
= j;
mcount
++ ;
}
}
getchar();
}
nv
= hcount * 2 + 2 ;
ne
= 0 ;
memset(head,
- 1 , sizeof (head));
for ( int i = 0 ; i < mcount; i ++ )
for ( int j = 0 ; j < hcount; j ++ )
addedge(i, j
+ mcount, 1 , abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y));
src
= nv - 2 ;
sink
= nv - 1 ;
for ( int i = 0 ; i < mcount; i ++ )
addedge(src, i,
1 , 0 );
for ( int i = 0 ; i < hcount; i ++ )
addedge(i
+ mcount, sink, 1 , 0 );
}
}g;

int main()
{
// freopen("t.txt", "r", stdin);
while (scanf( " %d%d " , & n, & m), n | m)
{
getchar();
g.build();
int ans = g.mincost();
printf(
" %d\n " , ans);
}
return 0 ;
}

你可能感兴趣的:(poj)