ZOJ 2404 Going Home 【最小费用最大流】

思路:

把房子和人看成点,加上源点和汇点。

源点和每个人连容量为1,权值为0的边。

每个人和每个房子连容量为1,权值为距离的边。

每个房子和汇点连容量为1,权值为0的边。

#include<stdio.h>
#include<queue>
#define MAXN 500
#define MAXM 10002*4
#define INF  10000000
using namespace std;
//起点编号必须最小,终点编号必须最大
bool vis[MAXN];                    //spfa中记录是否在队列里边
char pho[105][105];
struct point{
    int x,y;
}man[105],house[105];
struct edge{
    edge *next,*op;                //op是指向反向边
    int t,c,v;                     //t下一个点编号,c容量,v权值
}ES[MAXM],*V[MAXN];                //ES边静态邻接表,V点的编号
int N,M,S,T,EC=-1;                 //S源点最小,T汇点最大,EC当前边数
int demond[MAXN],sp[MAXN],prev[MAXN]; //spSPFA中记录距离,prev记录上一个点路径
edge *path[MAXN];                  //与prev同步记录,记录到上一条边
void addedge(int a,int b,int v,int c=INF){
    //printf("%d %d %d %d\n",a,b,v,c);
    edge e1={V[a],0,b,c,v},e2={V[b],0,a,0,-v};
    ES[++EC]=e1;V[a]=&ES[EC];
    ES[++EC]=e2;V[b]=&ES[EC];
    V[a]->op=V[b];V[b]->op=V[a];
}
int cal(point a,point b){
    return max(a.x-b.x,b.x-a.x)+max(a.y-b.y,b.y-a.y);
}
bool init(){
    int n,m;
    EC=-1;
    for(int i=0;i<=500;i++){
        V[i]=NULL;
    }
    scanf("%d%d",&n,&m);
    if(n==0&&m==0)return 0;
    for(int i=0;i<n;i++){
        scanf("%s",pho[i]);
    }
    int num_m=0,num_h=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(pho[i][j]==‘m‘){
                man[num_m++]={i,j};
            }
            else if(pho[i][j]==‘H‘){
                house[num_h++]={i,j};
            }
        }
    }
    for(int i=0;i<num_m;i++){
        for(int j=0;j<num_h;j++){
            addedge(i+1,num_m+j+1,cal(man[i],house[j]));
        }
    }
    for(int i=0;i<num_m;i++){
        addedge(0,i+1,0,1);
    }
    for(int i=0;i<num_h;i++){
        addedge(num_m+i+1,num_m+num_h+1,0,1);
    }
    S=0;T=num_m+num_h+1;
    return 1;
}
bool SPFA(){
    int u,v;
    for(u=S;u<=T;u++){
        sp[u]=INF;
    }
    queue<int>q;
    prev[S]=-1;
    q.push(S);
    sp[S]=0;
    vis[S]=1;
    while(!q.empty()){
        u=q.front();
        vis[u]=0;
        q.pop();
        for(edge *k=V[u];k;k=k->next){
            v=k->t;
            if(k->c>0&&sp[u]+k->v<sp[v]){
                sp[v]=sp[u]+k->v;
                prev[v]=u;
                path[v]=k;
                if(vis[v]==0){
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return sp[T]!=INF;
}
int argument(){
    int i,cost=INF,flow=0;
    edge *e;
    for(i=T;prev[i]!=-1;i=prev[i]){
        e=path[i];
        if(e->c<cost)cost=e->c;
    }
    for(int i=T;prev[i]!=-1;i=prev[i]){
        e=path[i];
        e->c-=cost;e->op->c+=cost;
        flow+=e->v*cost;
    }
    return flow;
}
int maxcostflow(){
    int Flow=0;
    while(SPFA()){
        Flow+=argument();
    }
    return Flow;
}
int main(){
    while(init())
        printf("%d\n",maxcostflow());
    return 0;
}
时间: 2024-10-09 01:20:04

ZOJ 2404 Going Home 【最小费用最大流】的相关文章

zoj 3885 The Exchange of Items 【最小费用最大流】

The Exchange of Items Time Limit: 2 Seconds      Memory Limit: 65536 KB Bob lives in an ancient village, where transactions are done by one item exchange with another. Bob is very clever and he knows what items will become more valuable later on. So,

【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 这道题其实就是模板题. 我的处理

POJ 3686.The Windy&#39;s 最小费用最大流

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5477   Accepted: 2285 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receives N orders for toys. The ma

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(因为每对匹配不能重复),费用为它们之间的距离即花费:然后建