Going Home - poj 2195(网络流 | 二分匹配)

题目大意:在一个网格里面有n个小男人和n个房子,现在想让每个小男人都有一个房子住,不过每个人移动一下都需要花费¥1,现在求出来最小的总花费。ps:可以认为网格的每个点都是很大的广场并且容纳所有的人,人可以走在有房子的点但是不进入房子。

分析:人-房子,很完美的带全都最小值匹配啊,人到一个房子的花费就是他们之间的曼哈顿距离,用这些距离构造一个二分图,然后用KM算法求出来最小费。下面是KM算法

***********************************************************************************************************************************************************************************

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#include<math.h>
using namespace std;

const int MAXN = 107;
const int oo = 1e9+7;

struct point{int x, y;}man[MAXN], house[MAXN];
char G[MAXN][MAXN];
int w[MAXN][MAXN], slack[MAXN], Nx, Ny;
int dx[MAXN], dy[MAXN], Ly[MAXN];
bool vx[MAXN], vy[MAXN];

void InIt()
{
    Nx = Ny = 0;

for(int i=1; i<MAXN; i++)
    {
        dx[i] = -oo;
        dy[i] = 0;
    }

}
bool Find(int i)
{
    vx[i] = true;
    for(int j=1; j<=Ny; j++)
    {
        if(!vy[j] && w[i][j] == dx[i]+dy[j])
        {
            vy[j] = true;
            if(!Ly[j] || Find(Ly[j]))
            {
                Ly[j] = i;
                return true;
            }
        }
        else if(!vy[j])
            slack[j] = min(slack[j], dx[i]+dy[j]-w[i][j]);
    }

return false;
}
int KM()
{
    int i, j;

memset(Ly, 0, sizeof(Ly));

for(i=1; i<=Nx; i++)
    {
        for(j=1; j<=Ny; j++)
            slack[j] = oo;
        while(true)
        {
            memset(vx, false, sizeof(vx));
            memset(vy, false, sizeof(vy));

if(Find(i) == true)
                break;

int d = oo;

for(j=1; j<=Ny; j++)
            {
                if(!vy[j] && d > slack[j])
                    d = slack[j];
            }

for(j=1; j<=Nx; j++)
            {
                if(vx[j])
                    dx[j] -= d;
            }
            for(j=1; j<=Ny; j++)
            {
                if(vy[j])
                    dy[j] += d;
                else
                    slack[j] -= d;
            }
        }
    }

int sum = 0;

for(i=1; i<=Ny; i++)
        sum += w[Ly[i]][i];

return -sum;
}

int main()
{
    int M, N;

while(scanf("%d%d", &M, &N), M+N)
    {
        int i, j;

InIt();

for(i=0; i<M; i++)
            scanf("%s", G[i]);

for(i=0; i<M; i++)
        for(j=0; j<N; j++)
        {
            if(G[i][j] == ‘m‘)
            {
                Nx++;
                man[Nx].x = i;
                man[Nx].y = j;
            }
            if(G[i][j] == ‘H‘)
            {
                Ny++;
                house[Ny].x = i;
                house[Ny].y = j;
            }
        }

for(i=1; i<=Nx; i++)
        for(j=1; j<=Ny; j++)
        {
            w[i][j] = fabs(man[i].x-house[j].x) + fabs(man[i].y-house[j].y);
            w[i][j] = -w[i][j];
            dx[i] = max(dx[i], w[i][j]);
        }

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

return 0;
}

时间: 2025-01-18 01:29:30

Going Home - poj 2195(网络流 | 二分匹配)的相关文章

poj 1469 COURSES (二分匹配)

COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16877   Accepted: 6627 Description Consider a group of N students and P courses. Each student visits zero, one or more than one courses. Your task is to determine whether it is poss

HDU 3036 Escape 网格图多人逃生 网络流||二分匹配 建图技巧

前言 在编程过程中总结归纳出来的一种编程经验,从而形成的设计思想称为设计模式. 设计模式有23种.它适用于所有的编程语言. 常用的有创新型的设计模式:简单工厂.抽象工厂和单例模式:行为型的设计模式:模板设计模式.观察者模式和命令模式:结构性的设计模式:适配器设计模式.代理模式(静态和动态两种,典型的有在spring的AOP编程中使用)和装饰器设计模式. 正文 单例模式(singleton) 保证一个类在内存中只能创建一个实例. 1.实现步骤: 1)将构造器私有化,即使用private修饰构造器

POJ 3041 - 最大二分匹配

这道题实现起来还是比较简单的,但是理解起来可能有点困难. 我最开始想到的是贪心法,每次消灭当前小行星最多的一行或一列.然而WA了.Discuss区里已经有高人给出反例. 下面给出正确的解法 我们把行和列抽象成点,把小行星抽象成边,每出现一个小行星,就把其行列所对应的点连起来.这样就形成了一个无向图$G=\left(V, E\right)$.问题就转化为了求这个图G中的最小点覆盖,即求一个元素数量尽可能小的点集$V' \subset V$,$E$中的所有边均与其内的一点相连. 最小点覆盖问题是一个

Ombrophobic Bovines (poj 2391 网络流+二分+Floyd)

Language: Default Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15733   Accepted: 3434 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in th

poj COURSES(二分匹配)

题目链接:http://poj.org/problem?id=1469 COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17135   Accepted: 6730 Description Consider a group of N students and P courses. Each student visits zero, one or more than one courses. Your tas

poj 2446 Chessboard (二分匹配)

Chessboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12800   Accepted: 4000 Description Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of cards with size 1 * 2

POJ 3228 网络流+二分&amp;并查集

点击打开链接 题意:有n个城镇,第一行是金矿和金子数量,然后第二行是装金子的地方和能装的数量,在下面是m条道路,问你选择的道路中最大值最小,使得所有金子运到装金子的地方 思路:最大值最小,根本不用考虑一看就是二分,然后想了想就是个网络流的模型嘛,很简单,被坑了几次道路是双向的,改过之后A掉,然后看了看讨论还可以用并查集写,这里两种方法都写了,先是网络流的直接二分最大值,然后满足条件的边建模型,跑一边就行了 #include <queue> #include <vector> #in

Optimal Milking (poj 2112 网络流+二分+floyd)

Language: Default Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 12951   Accepted: 4688 Case Time Limit: 1000MS Description FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures among the C (1 <

D - Going Home POJ - 2195 网络流

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, unt