[POJ 2195] Going Home

[题目链接]

          http://poj.org/problem?id=2195

[算法]

          KM算法求二分图带权最小匹配
[代码]

         

#include <algorithm>  
#include <bitset>  
#include <cctype>  
#include <cerrno>  
#include <clocale>  
#include <cmath>  
#include <complex>  
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <ctime>  
#include <deque>  
#include <exception>  
#include <fstream>  
#include <functional>  
#include <limits>  
#include <list>  
#include <map>  
#include <iomanip>  
#include <ios>  
#include <iosfwd>  
#include <iostream>  
#include <istream>  
#include <ostream>  
#include <queue>  
#include <set>  
#include <sstream>  
#include <stdexcept>  
#include <streambuf>  
#include <string>  
#include <utility>  
#include <vector>  
#include <cwchar>  
#include <cwctype>  
#include <stack>  
#include <limits.h>
using namespace std;
#define MAXN 5010
const int inf = 2e9;

int i,j,l1,l2,n,m,delta;
int match[MAXN],la[MAXN],lb[MAXN];
bool visiteda[MAXN],visitedb[MAXN];
int w[MAXN][MAXN];
pair<int,int> man[MAXN],house[MAXN];
char mp[MAXN][MAXN];

inline int dist(pair<int,int> a,pair<int,int> b)
{
        return abs(a.first - b.first) + abs(a.second - b.second);
}
inline bool dfs(int u)
{
        int v;
        visiteda[u] = true;
        for (v = 1; v <= l1; v++)
        {
                if (!visitedb[v])
                {
                        if (la[u] + lb[v] - w[u][v] == 0)
                        {
                                visitedb[v] = true;
                                if (!match[v] || dfs(match[v]))
                                {
                                        match[v] = u;
                                        return true;
                                }
                        } 
                }
        }
        return false;
}
inline int KM()
{
        int i,j,k,ret;
        for (i = 1; i <= l1; i++)
        {
                la[i] = -inf;    
                lb[i] = 0;
                match[i] = 0;
                for (j = 1; j <= l1; j++) la[i] = max(la[i],w[i][j]);    
        }        
        for (i = 1; i <= l1; i++)
        {
                while (true)
                {
                        for (j = 1; j <= l1; j++) visiteda[j] = visitedb[j] = false;
                        if (dfs(i)) break;
                        delta = inf;
                        for  (j = 1; j <= l1; j++)
                        {
                                if (visiteda[j])
                                {
                                        for (k = 1; k <= l1; k++)
                                        {
                                                if (!visitedb[k])
                                                        delta = min(delta,la[j] + lb[k] - w[j][k]);
                                        }
                                }
                        }
                        for (j = 1; j <= l1; j++)
                        {
                                if (visiteda[j]) la[j] -= delta;
                                if (visitedb[j]) lb[j] += delta;
                        }
                }
        }
        ret = 0;
        for (i = 1; i <= l1; i++) ret += w[match[i]][i];
        return ret;
}
 
int main() 
{
        
        while (scanf("%d%d",&n,&m) && (n || m))
        {
                l1 = l2 = 0;
                for (i = 1; i <= n; i++) scanf("%s",mp[i] + 1);
                for (i = 1; i <= n; i++)
                {
                        for (j = 1; j <= m; j++)
                        {
                                if (mp[i][j] == 'm') man[++l1] = make_pair(i,j);
                                if (mp[i][j] == 'H') house[++l2] = make_pair(i,j);
                        }
                }
                for (i = 1; i <= l1; i++)
                {
                        for (j = 1; j <= l1; j++)
                        {
                                w[i][j] = -dist(man[i],house[j]);
                        }
                }
                printf("%d\n",-KM());
        }
         
        return 0;
    
}

 

posted @ 2018-08-07 14:57  evenbao  阅读(120)  评论(0编辑  收藏  举报