最小费用最大流,地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=2195
#include <stdio.h>

const int MAX = 3276700;

const int LEN = 205;

int house[LEN][2];
int hl;
int man[LEN][2];
int ml;

void init ()
{
    
    hl 
= ml = 0;
}


struct
{
    
int c;
    
int f;
    
int weight;
}
map[LEN][LEN];

int nearl[LEN][LEN];

void initm ( int n )
{

    
for ( int i=0; i<n; i++ )
    
{
        nearl[i][
0= 1;
        
for ( int j=0; j<n; j++ )
        
{
            map[i][j].c 
= map[i][j].f = map[i][j].weight = 0;
        }

    }

}


void add ( int a, int b, int c, int weight )
{

    
if ( ! map[a][b].c && ! map[b][a].c )
    
{
        nearl[a][ nearl[a][
0]++ ] = b;
        nearl[b][ nearl[b][
0]++ ] = a;
    }

    map[a][b].c 
+= c;
    map[a][b].weight 
+= weight;
}


int cost[LEN];
int road[LEN];

int ad ( int s, int t, int *mincost )
{

    
int p = t;
    
int min = MAX;

    
while ( p != s )
    
{
        
if ( min > map[ road[p] ][p].c - map[ road[p] ][p].f )
        
{
            min 
= map[ road[p] ][p].c - map[ road[p] ][p].f;
        }

        p 
= road[p];
    }


    p 
= t;
    
while ( p != s )
    
{
        map[ road[p] ][p].f 
+= min;
        map[ p ][ road[p] ].f 
-= min;
        
*mincost += min * map[ road[p] ][p].weight;
        p 
= road[p];
    }

    
return min;
}


int mima ( int s, int t, int n, int *mincost )
{

    
int maxflow = 0;
    
*mincost = 0;
    
do
    
{
        road[t] 
= -1;
        cost[s] 
= 0;
        
for ( int i=1; i<n; i++ )
        
{
            cost[i] 
= MAX;
        }


        
int flag = 1;
        
while ( flag )
        
{
            flag 
= 0;
            
for ( int v=0; v < n; v++ )
            
{
                
for ( int u=1; u<nearl[v][0]; u++ )
                
{
                    
if ( map[ nearl[v][u] ][v].f < map[ nearl[v][u] ][v].c && cost[ nearl[v][u] ] < MAX )
                    
{
                        
if ( cost[v] > cost[ nearl[v][u] ] + map[ nearl[v][u] ][v].weight )
                        
{
                            cost[v] 
= cost[ nearl[v][u] ] + map[ nearl[v][u] ][v].weight;
                            road[v] 
= nearl[v][u];
                            flag 
= 1;
                        }

                    }

                }

            }

        }

        
if ( road[t] != -1 )
        
{
            maxflow 
+= ad ( s, t, mincost );
        }

    }
while ( road[t] != -1 );

    
return maxflow;
}


int abs ( int a )
{

    
return a > 0 ? a : -a;
}


int main ()
{

    
int n, m;

    
while ( scanf ( "%d%d"&n, &m ) != EOF && ( n || m ) )
    
{
        
int i, j;
        
char in[105];

        gets ( in );
        init ();
        
for ( i=0; i<n; i++ )
        
{
            scanf ( 
"%s"&in );
            
for ( j=0; j<m; j++ )
            
{
                
if ( in[j] == 'H' )
                
{
                    house[hl][
0= i;
                    house[hl][
1= j;
                    hl 
++;
                    
continue;
                }

                
if ( in[j] == 'm' )
                
{
                    man[ml][
0= i;
                    man[ml][
1= j;
                    ml 
++;
                    
continue;
                }


            }

        }


        initm ( ml
+hl+2 );
        
for ( i=0; i<ml; i++ )
        
{
            add ( 
0, i+110 );
            add ( 
+1000 );
        }

        
for ( i=0; i<ml; i++ )
        
{
            
for ( j=0; j<hl; j++ )
            
{
                
int weight = abs ( man[i][0]-house[j][0] ) + abs ( man[i][1]-house[j][1] );
                add ( i
+1, ml+1+j, 1, weight );
                add ( ml
+1+j, i+10-weight );
            }

        }

        
for ( j=0; j<hl; j++ )
        
{
            add ( ml
+1+j, ml+hl+110 );
            add ( ml
+hl+1, ml+1+j, 00 );
        }


        
int mincost;

        mima ( 
0, ml+hl+1, ml+hl+2&mincost );

        printf ( 
"%d\n", mincost );
    }

    
return 0;
}