HDU1533 Going Home(最小费用最大流 spfa模版)

题意:

给你一个N行M列的矩阵,其中“.”代表空地,“H”代表房子,“m”代表人,其中有n个房子和n个人。现在要求每个人进入一间房子,且人走一步需要支付1美元。

求最小需要花费多少美元才能让所有人都进入到房子中(每个人只能进入一间房子,每个房子只能容纳一个人)。

建图思路与安排工作那道题一样,设置一个超级源点(我习惯设置为0)和一个超级汇点,然后超级源点连接每个人(流量为1费用为0),

每个人连接每个房子(流量为1费用为人与房子的距离),然后每个房子连接超级汇点(流量为1费用为0)。

跑一遍spfa模版就出来了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <cmath>
#include <vector>
#include <algorithm>
#include <limits.h>
using namespace std;
#define inf 1e8
#define maxn 205
#define maxm 100000
int head[maxn],eid;
int dis[maxn];
bool vis[maxn];
int a[maxn];
int pre[maxn];
int cnt1,cnt2,cnt,result;
int hx[maxn],hy[maxn],mx[maxn],my[maxn],cap[maxn][maxn];
struct node
{
    int u,v,cap,next,cost;
}eg[maxm];
int fun(int x,int y)
{
    return fabs(mx[x]-hx[y])+fabs(my[x]-hy[y]);
}
void add(int u,int v,int cap,int cost)
{
    eg[eid].u=u;
    eg[eid].v=v;
    eg[eid].cap=cap;
    eg[eid].next=head[u];
    eg[eid].cost=cost;
    head[u]=eid++;
    eg[eid].u=v;
    eg[eid].v=u;
    eg[eid].cap=0;
    eg[eid].next=head[v];
    eg[eid].cost=-cost;
    head[v]=eid++;
}
void makemap()
{
    for(int i=1;i<=cnt2;i++)
    {
        add(0,i,1,0);
        for(int j=1;j<=cnt1;j++)
        {
            add(i,cnt2+j,1,fun(i,j));
        }
    }
    for(int j=1;j<=cnt1;j++)
        add(cnt2+j,cnt,1,0);
}
bool spfa(int s,int t,int &flow,int &cost)
{
    memset(vis,false,sizeof(vis));
    for(int i=0;i<maxn;i++)
        dis[i]=inf;
    dis[s]=0;
    vis[s]=true;
    pre[s]=0;
    a[s]=inf;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=head[u];i!=-1;i=eg[i].next)
        {
            if(eg[i].cap&&dis[eg[i].v]>dis[u]+eg[i].cost)
            {
                dis[eg[i].v]=dis[u]+eg[i].cost;
                pre[eg[i].v]=i;
                a[eg[i].v]=min(a[u],eg[i].cap);
                if(!vis[eg[i].v])
                {
                    q.push(eg[i].v);
                    vis[eg[i].v]=true;
                }
            }
        }
    }
    if(dis[t]==inf) return false;
    flow+=a[t];
    cost+=dis[t]*a[t];
    int u=t;
    while(u!=s)
    {
        eg[pre[u]].cap-=a[t];
        eg[pre[u]^1].cap+=a[t];
        u=eg[pre[u]].u;
    }
    return true;
}
int mincost(int s,int t)
{
    int flow=0,cost=0;
    while(spfa(s,t,flow,cost));
    return cost;
}
void init()
{
    memset(head,-1,sizeof(head));
    eid=0;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int n,m;
    char s[maxn];
    while(~scanf("%d%d",&n,&m)&&n)
    {
        init();
        cnt1=cnt2=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",s);
            for(int j=0;s[j]!=‘\0‘;j++)
            {
                if(s[j]==‘H‘)
                {
                    cnt1++;
                    hx[cnt1]=i;
                    hy[cnt1]=j;
                }
                else if(s[j]==‘m‘)
                {
                    cnt2++;
                    mx[cnt2]=i;
                    my[cnt2]=j;
                }
            }
        }
        cnt=cnt1+cnt2+1;
        makemap();
        printf("%d\n",mincost(0,cnt));
    }
    return 0;
}
时间: 2024-08-09 02:41:23

HDU1533 Going Home(最小费用最大流 spfa模版)的相关文章

[hdu1533]二分图最大权匹配 || 最小费用最大流

题意:给一个n*m的地图,'m'表示人,'H'表示房子,求所有人都回到房子所走的距离之和的最小值(距离为曼哈顿距离). 思路:比较明显的二分图最大权匹配模型,将每个人向房子连一条边,边权为曼哈顿距离的相反数(由于是求最小,所以先取反后求最大,最后再取反回来即可),然后用KM算法跑一遍然后取反就是答案.还可以用最小费用最大流做,方法是:从源点向每个人连一条边,容量为1,费用为0,从每个房子向汇点连一条边,容量为1,费用为0,从每个人向每个房子连一条边,容量为1,费用为曼哈顿距离的值,建好图后跑一遍

【BZOJ3876】【Ahoi2014】支线剧情 有下界的最小费用最大流

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43025375"); } [BZOJ2324]营救皮卡丘 这道题也是一道有下界的最小费用最大流. 我的题解地址:http://blog.csdn.net/vmurder/article/details/41378979 这道题其实就是模板题. 我的处理

P3381 【模板】最小费用最大流

P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一行,包含两个整数,依次为最大流量和在最大流量情况下的

C++之路进阶——最小费用最大流(支线剧情)

F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入.输出语句及数据类型及范围,避免无谓的RE出现. 3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 542  Solved: 332[Submit

hdu 4494 Teamwork 最小费用最大流

Teamwork Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4494 Description Some locations in city A has been destroyed in the fierce battle. So the government decides to send some workers to repair these location

POJ - 2195 Going Home(最小费用最大流)

1.N*M的矩阵中,有k个人和k个房子,每个人分别进入一个房子中,求所有人移动的最小距离. 2.人看成源点,房子看成汇点,求最小费用最大流. 建图-- 人指向房子,容量为1,费用为人到房子的曼哈顿距离. 建立超级源点和超级汇点:超级源点指向人,容量为1,费用为0:超级汇点指向房子,容量为1,费用为0. 求超级源点到超级汇点的最小费用最大流即可. ps:容量为什么都设为1?---有待研究.. 3. 1.Bellman-Ford: #include<iostream> #include<st

hdu 1853 Cyclic Tour 最小费用最大流

题意:一个有向图,现在问将图中的每一个点都划分到一个环中的最少代价(边权和). 思路:拆点,建二分图,跑最小费用最大流即可.若最大流为n,则说明是最大匹配为n,所有点都参与,每个点的入度和出度又是1,所以就是环. /********************************************************* file name: hdu1853.cpp author : kereo create time: 2015年02月16日 星期一 17时38分51秒 *******

最小费用最大流

Farm Tour http://poj.org/problem?id=2135 建图再说吧 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<map> 6 #include<stack> 7 #include<queue> 8 #include<vector> 9 #include&l

POJ 2195 地图的最小费用最大流

思路:这题刚开始看就知道是最小费用最大流了,因为求出最优嘛,而且要m,H要一一对应,所以不是二分图匹配就是最小费用最大流. 不过,刚开始还在想每个m与H之间的最小花费如何求,难道要用dfs搜索吗?这样想之后看了下题目给的时间是1000ms,然后就把dfs搜索m与H之间的最短距离排除了.然后想了想,其实尼玛太简单了,因为题目说了只能垂直与竖直的走,所以最短距离不就是两个横坐标相减与两个纵坐标相减之和嘛! 然后每对m与H之间都连边,流量为1(因为每对匹配不能重复),费用为它们之间的距离即花费:然后建