POJ - 2195 最小费用最大流

题意:每个人到每个房子一一对应,费用为曼哈顿距离,求最小的费用

题解:单源点汇点最小费用最大流,每个人和房子对于建边

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cassert>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;
using namespace __gnu_cxx;

const double g=10.0,eps=1e-7;
const int N=300+10,maxn=10000+10,inf=0x3f3f3f;

struct edge{
    int to,Next,c;
    int cost;
}e[maxn<<2];
int cnt,head[N];
int s,t,ans[N][N];
int dis[N],path[N],pre[N];
void add(int u,int v,int c,int cost)
{
   // cout<<u<<" "<<v<<" "<<c<<" "<<cost<<endl;
    e[cnt].to=v;
    e[cnt].c=c;
    e[cnt].cost=cost;
    e[cnt].Next=head[u];
    head[u]=cnt++;
    e[cnt].to=u;
    e[cnt].c=0;
    e[cnt].cost=-cost;
    e[cnt].Next=head[v];
    head[v]=cnt++;
}
bool spfa()
{
    memset(pre,-1,sizeof pre);
    memset(dis,inf,sizeof dis);
    dis[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=head[x];~i;i=e[i].Next)
        {
            int te=e[i].to;
            if(e[i].c>0&&dis[x]+e[i].cost<dis[te])
            {
                dis[te]=dis[x]+e[i].cost;
                pre[te]=x;
                path[te]=i;
                q.push(te);
            }
        }
    }
    return pre[t]!=-1;
}
int mincostmaxflow()
{
    int cost=0,flow=0;
    while(spfa())
    {
        int f=inf;
        for(int i=t;i!=s;i=pre[i])
            if(f>e[path[i]].c)
                f=e[path[i]].c;
        flow+=f;
        cost+=dis[t]*f;
        for(int i=t;i!=s;i=pre[i])
        {
            e[path[i]].c-=f;
            e[path[i]^1].c+=f;
        }
    }
    return cost;
}
void init()
{
    cnt=0;
    memset(head,-1,sizeof head);
}
int main()
{
   /* ios::sync_with_stdio(false);
    cin.tie(0);*/
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m)break;
        init();
        int house=0,man=0;
        pii ho[N],ma[N];
        for(int i=1;i<=n;++i)
        {
            char a[N];
            scanf("%s",a+1);
            for(int j=1;j<=m;j++)
            {
                if(a[j]==‘H‘)ho[++house]=mp(i,j);
                else if(a[j]==‘m‘)ma[++man]=mp(i,j);
            }
        }
        for(int i=1;i<=house;i++)
        {
            for(int j=1;j<=man;j++)
            {
                int cost=abs(ho[i].fi-ma[j].fi)+abs(ho[i].se-ma[j].se);
            //    cout<<i<<" "<<j<<" "<<cost<<endl;
                add(i,house+j,inf,cost);
               // add(house+j,i,inf,cost);
            }
        }
        s=house+man+1,t=house+man+2;
        for(int i=1;i<=house;i++)add(s,i,1,0);
        for(int i=1;i<=man;i++)add(i+house,t,1,0);
        printf("%d\n",mincostmaxflow());
    }
    return 0;
}
/*******************

********************/

时间: 2024-10-01 04:42:53

POJ - 2195 最小费用最大流的相关文章

poj 2195 最小费用最大流模板

/*Source Code Problem: 2195 User: HEU_daoguang Memory: 1172K Time: 94MS Language: G++ Result: Accepted Source Code */ #include <iostream> #include <stdio.h> #include <queue> #include <math.h> #include <string.h> using namespa

poj 2516 最小费用最大流

Language: Default Minimum Cost Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 14334   Accepted: 4908 Description Dearboy, a goods victualer, now comes to a big problem, and he needs your help. In his sale area there are N shopkeepers (m

poj 2135(最小费用最大流)

Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14730   Accepted: 5614 Description When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 <= N <= 1000) fields numbered 1..N, the first of

poj 2135 最小费用最大流初步

这个题的意思是农夫约翰要呆人参观他的农场, 刚开始从1开始走, 走到N后又返回1点, 两次不能走相同的路, 问农夫约翰走的最短的路是多少?? 我们可以用最小MCMF来解决这个问题, 对于图中的每一条边, 我们建立了两条流量为1, 费用为边权的边, 再增加一个源点和一个汇点, 源点指向1, 流量为2,费用为0, N指向汇点, 流量为2费用为0, 然后求出最小费用即可, 代码如下: #include <cstdio> #include <algorithm> #include <

POJ 3680 最小费用最大流

这题来源:<算法竞赛经典入门-训练指南>中的367页:区间k覆盖问题. 思路:这题建图比较机智,我刚开始想到能建的图也就是离散化后两个端点连边,流量为1,费用为负的权值(因为求的是最大费用最大流),然后再加上源点和汇点,也就如此而已:但是这样建图样例第二和第四个不正确,因为中间没有联系的没连边,然后k就没用了. 原来最重要的连边是i和i+1之间的连边,流量为k,费用为0:为什么要连这些边呢,刚开始我也没想明白,后面才知道,因为有的端点之间你要让它们产生联系并且受制与k次,那么就得把这些点都连边

POJ 3422 最小费用最大流

链接: http://poj.org/problem?id=3422 题解: 关键是如何处理"只能获取一次"的问题,为此可以为每个点创建伪点,由两条有向边相连.原始点到伪点连一条容量为1,权值为负分数的边:原始点到伪点连一条容量为无穷,权值为0的边.前者表示分数只能拿一次,后者表示第二次第三次--可以继续走这个点,但是不拿分数.负权是因为题目要求的是"最大费用".又因为最多走同一个点K次,所以此处的无穷大取K就行了. 代码: 1 #include <map&g

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

http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大流.最小费用最大流是保证在流量最大的情况下,使得费用最小. 建图是把S->人->家->T这些边弄上形成一个网络,边的容量是1(因为一个人只能和一个家匹配),边的费用是曼哈顿距离,反向边的费用是-cost. 算法的思想大概是通过SPFA找增广路径,并且找的时候费用是可以松弛的.当找到这样一条增

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

题目链接:http://poj.org/problem?id=2195 题意:n*m的矩阵,地图上有若干个人(m)和房子(H),且人与房子的数量一致.man每移动一格费用为1,一个房子只能住一个人.现在要求所有的人出发,都入住房子,求最少话费. 思路:建立一个超级源点和汇点,源点与人相连费用为0,容量为1,人与房子相连,费用为人与房子的距离,容量为1,房子与汇点相连,费用为0,容量为1 #include <iostream> #include <cstdlib> #include

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