Going Home

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2514    Accepted Submission(s): 1269
Problem Description
On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every
step he moves, until he enters a house. The task is complicated with the restriction that each house can accommodate only one little man.



Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates
there is a little man on that point.



You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.
 
Input
There are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the
map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of 'H's and 'm's on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.
 
Output
For each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay.
 
Sample Input
2 2
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0
 
Sample Output
2
10
28
 
题解:把每一个m到H的距离保存起来当作一个边。值记录成负的,由于要求最小距离,常规KM计算的是最大值

#include <iostream>

#include <cstring>

#define MAX (1<<30)

#define MIN -MAX

using namespace std;

struct ssss

{

    int x,y;

};

ssss s1[111],s2[111];

int n,m,l1,l2,map[111][111];

int rode[111],r[111];

bool vx[111],vy[111];

int sx[111],sy[111];

int dfs(int x)

{

    vx[x]=1;    //标记增广路左边已訪问的点

    int i,j,k,l;

    for(i=0;i<l2;i++)

    if(!vy[i])

    {

        k=sx[x]+sy[i]-map[x][i];

        if(k==0)

        {

            vy[i]=1;//訪问它再标记已訪问

            if(rode[i]==-1||dfs(rode[i]))   //假设右边的点没有匹配或者有匹配(继续用他的匹配点继续找)

            {

                rode[i]=x;  //记录右边点匹配到的左边点的序号

                return 1;

            }

        }else if(r[i]>k)r[i]=k;     //记录右端点没訪问的边的最小差值。用来导入

    }

    return 0;

}

int Dinic()

{

    int i,j,k,l;

    memset(sy,0,sizeof(sy));    //标记右端点权值

    memset(rode,-1,sizeof(rode));   //右端点匹配点初始化为-1

    for(i=0;i<l1;i++)

    {

        sx[i]=MIN;

        for(j=0;j<l2;j++)

        sx[i]=max(sx[i],map[i][j]); //左端点权值取最大的边的值

    }

    for(i=0;i<l1;i++)

    {

        for(j=0;j<l2;j++)r[j]=MAX;

        while(1)

        {

            memset(vx,0,sizeof(vx));    //訪问标记初始化

            memset(vy,0,sizeof(vy));

            if(dfs(i))break;    //匹配到了就结束

            k=MAX;

            for(j=0;j<l2;j++)

            if(!vy[j])k=min(k,r[j]);    //不然导入差值最小的边(这是保证匹配的总值从最大逐渐减小)

            for(j=0;j<l1;j++)

            if(vx[j])sx[j]-=k;  //左端点权值减小

            for(j=0;j<l2;j++)

            if(vy[j])sy[j]+=k;  //右端点权值曾加

            //这样导入了边之后其它匹配不变x+y=(x-k)+(y+k)

        }

    }

    for(i=k=0;i<l2;i++)

    k+=map[rode[i]][i];

    return -k;

}

int bb(int x)

{

    return x>0?x:-x;

}

int main (void)

{

    int i,j,k,l;

    char c;

    while(cin>>n>>m&&n)

    {

        l1=l2=0;

        for(i=0;i<n;i++)

        for(j=0;j<m;j++)

        {

            cin>>c;

            if(c=='m')

            {

                s1[l1].x=i;

                s1[l1].y=j;

                l1++;

            }

            if(c=='H')

            {

                s2[l2].x=i;

                s2[l2].y=j;

                l2++;

            }

        }

        for(i=0;i<l1;i++)

        for(j=0;j<l2;j++)

        {

            k=bb(s1[i].x-s2[j].x)+bb(s1[i].y-s2[j].y);

            map[i][j]=(k<0?k:-k);

        }

        cout<<Dinic()<<endl;

    }

    return 0;

}

HDU--1533--Going Home--KM算法的更多相关文章

  1. hdu 1533 Going Home (KM)

    Going HomeTime Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  2. [ACM] HDU 1533 Going Home (二分图最小权匹配,KM算法)

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  3. hdu 2255 奔小康赚大钱--KM算法模板

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:有N个人跟N个房子,每个人跟房子都有一定的距离,现在要让这N个人全部回到N个房子里面去,要 ...

  4. hdu 2853 Assignment KM算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2853 Last year a terrible earthquake attacked Sichuan ...

  5. hdu 2426 Interesting Housing Problem 最大权匹配KM算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2426 For any school, it is hard to find a feasible ac ...

  6. 【HDU 1533】 Going Home (KM)

    Going Home Problem Description On a grid map there are n little men and n houses. In each unit time, ...

  7. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  8. HDU 2255 奔小康赚大钱 (KM算法 模板题)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  9. hdu 3488(KM算法||最小费用最大流)

    Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submis ...

  10. HDU:2255-奔小康赚大钱(KM算法模板)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Mem ...

随机推荐

  1. HDU3368+枚举

    题意看不懂的直接看百度百科对黑白棋的解释... 做法:分情况讨论,一共8个方向. /* 搜索 */ #include<stdio.h> #include<string.h> ; ...

  2. 基于FFmpeg和Qt的播放器 QtAV库

    http://blog.csdn.net/ibingow/article/details/8144795

  3. Ubuntu下APACHE HTTPS安装和配置

    http://blog.csdn.net/newjueqi/article/details/9789659

  4. stream_iterator、ostream_iterator 使用初探

    STL定义了供输入及输出的iostream iterator类,称为 istream_iterator和ostream_iterator,分别支持单一型别的元素的读取和写入. 使用方法: 1.包含头文 ...

  5. jquery ajax传递数组给php

    写成:var data = {'item[]':item}; $.post(url,data,function(return_data) 写成item:item会导致数据缺失. 更多:http://w ...

  6. 【Python Network】分解DNS查询结果

    针对DNS查询records,通过NS.PTR.CNAME和MX类别不同,返回数据将包含另外主机名.为了解最终的IP地址,通过将返回信息分解.继续使用PyDNS获取详细信息. #! /usr/bin/ ...

  7. hdu4597Play Game(记忆化)

    链接 通化邀请赛的题 貌似不怎么难 记忆化DP 状态方程类似于2维的 只是变成了4维  每次有四种方向去搜 取最棒的 判断好边界条件 #include <iostream> #includ ...

  8. jdbcTemplate 获取数据表结构

    jdbcTemplate 操作方法 /** *1.方法一: */ String sql = "select * from "+ tableName; //RowCountCallb ...

  9. 解决Dagger2和butterknife冲突

    dagger2 和 RxJava butterknife 以及 Retrofit使用起来非常酸爽 代码非常干净清晰 动手尝试 配置编译 DaggerAppComponent的时候 出现问题 配置dag ...

  10. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]Contents

    I find it may cost me so much time in doing such solutions to exercises and problems....I am sorry t ...