POJ 2195 Going Home(KM)

来源:互联网 发布:免费开源asp源码 手机 编辑:程序博客网 时间:2024/05/21 09:54

题目链接:POJ 2195 Going Home

人是可以踩踏房子经过的,那距离就很好求了。建图求距离,把距离设为负的,就转化为KM了,最后别忘了负号。

#include <iostream>#include <cstring>#include <cstdio>#include <cmath>using namespace std;const int MAX_N = 100 + 30;const int INF = 0x3f3f3f3f;int n_x, n_y;//两边的点数int G[MAX_N][MAX_N];//二分图权值int link[MAX_N], l_x[MAX_N], l_y[MAX_N];//y中各店匹配的状态,  x,y,中的点标号int slack[MAX_N];bool vis_x[MAX_N], vis_y[MAX_N];bool DFS(int x){    vis_x[x] = true;    for(int y = 0; y < n_y; y++)    {        if(vis_y[y])            continue;        int temp = l_x[x] + l_y[y] - G[x][y];        if(temp == 0)        {            vis_y[y] = true;            if(link[y] == -1 || DFS(link[y]))            {                link[y] = x;                return true;            }        }        else if(slack[y] > temp)            slack[y] = temp;    }    return false;}int KM(){    memset(link, -1, sizeof(link));    memset(l_y, 0, sizeof(l_y));    for(int i = 0; i < n_x; i++)    {        l_x[i] = -INF;        for(int j = 0; j < n_y; j++)            if(G[i][j] > l_x[i])                l_x[i] = G[i][j];    }    for(int x = 0; x < n_x; x++)    {        for(int i = 0; i < n_y; i++)            slack[i] = INF;        while(true)        {            memset(vis_x, false, sizeof(vis_x));            memset(vis_y, false, sizeof(vis_y));            if(DFS(x))                break;            int d = INF;            for(int i = 0; i < n_y; i++)                if(!vis_y[i] && d > slack[i])                    d = slack[i];            for(int i = 0; i < n_y; i++)                if(vis_x[i])                    l_x[i] -= d;            for(int i = 0; i < n_y; i++)            {                if(vis_y[i])                    l_y[i] += d;                else                    slack[i] -= d;            }        }    }    int res = 0;    for(int i = 0; i < n_y; i++)        if(link[i] != -1)            res += G[link[i]][i];    return res;}char _map[MAX_N][MAX_N];struct Man{    int x, y;};struct House{    int x, y;};Man man[MAX_N];House house[MAX_N];int main(){    int n, m;    while(scanf("%d%d", &n, &m) != EOF && n + m)    {        for(int i = 0; i < n; i++)            scanf("%s", _map[i]);        int cnt_man = 0, cnt_house = 0;        for(int i = 0; i < n; i++)        {            for(int j = 0; j < m; j++)            {                if(_map[i][j] == 'm')                {                    man[cnt_man].x = i;                    man[cnt_man++].y = j;                }                else if(_map[i][j] == 'H')                {                    house[cnt_house].x = i;                    house[cnt_house++].y = j;                }            }        }        n_x = cnt_man;        n_y = cnt_house;        for(int i = 0; i < cnt_man; i++)            for(int j = 0; j < cnt_house; j++)                G[i][j] = -(abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y));        printf("%d\n", -KM());    }    return 0;}


0 0