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

题意:给你一个图,H表示房子,m表示人,为你这些人进到房子的最小话费是多少。

直接把源点和人建边,人和房子建边,房子和汇点建边。

跑一边最小费用最大流就好。

AC代码:

#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
const int MM=1e5;
const int inf=1<<30;
struct MCMF{
    struct Edge{
        int from,to,cap,flow,cost,next;
        Edge(){}
        Edge(int from,int to,int cap,int flow,int cost,int next){
            this->from=from;
            this->to=to;
            this->cap=cap;
            this->flow=flow;
            this->cost=cost;
            this->next=next;
        }
    }ed[666666];
    int n,m,s,t,head,tail,lnum;
    int vis[MM],dis[MM],pre[MM];//pre 上一条弧
    int cag[MM],que[MM*3],start[MM];//cag 可改进量

    void init(){
        lnum=0;
        rep(i,s,t) start[i]=-1;
    }

    void add(int x,int y,int v,int c){
        ed[lnum]=Edge(x,y,v,0,c,start[x]);
        start[x]=lnum++;
        ed[lnum]=Edge(y,x,0,0,-c,start[y]);
        start[y]=lnum++;
    }

    bool spfa(int& flow,int& cost){
        rep(i,s,t) dis[i]=inf,vis[i]=0;
        head=tail=0;
        dis[s]=0;vis[s]=1;pre[s]=0;cag[s]=inf;
        que[tail++]=s;
        while(head<tail){
            int x=que[head++];
            vis[x]=0;
            for(int i=start[x];~i;i=ed[i].next){
                Edge& e=ed[i];
                if(e.cap>e.flow&&dis[e.to]>dis[x]+e.cost){
                    dis[e.to]=dis[x]+e.cost;
                    pre[e.to]=i;
                    cag[e.to]=min(cag[x],e.cap-e.flow);
                    if(!vis[e.to]){
                        que[tail++]=e.to;
                        vis[e.to]=1;
                    }
                }
            }
        }
        if(dis[t]==inf) return false;
        flow+=cag[t];
        cost+=dis[t]*cag[t];
        int x=t;
        while(x!=s){
            ed[pre[x]].flow+=cag[t];
            ed[pre[x]^1].flow-=cag[t];
            x=ed[pre[x]].from;
        }
        return true;
    }

    int Mincost(){
        int flow=0,cost=0;
        while((spfa(flow,cost)));
        return cost;
    }

}mc;
struct node{
	int x,y,idx;
};
node hou[MM],man[MM];
int toth,totm;
int main()
{
	char mp[100][100];
	int n,m;
	while(~scanf("%d%d",&n,&m)){
		if(n==0 && m==0 ) break;
		mc.init();
		toth = totm = 0;
		for(int i=1;i<=n;i++){
			scanf("%s",mp[i]+1);
		}
		mc.s=0;mc.t=n*m+1;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++)
			{
				if(mp[i][j]=='m')
				{
					man[totm].idx=(i-1)*m+j;
					man[totm].x=i;
					man[totm++].y=j;
				}
				else if(mp[i][j]=='H')
				{
					hou[toth].idx=(i-1)*m+j;
					hou[toth].x=i;
					hou[toth++].y=j;
				}
			}
		}
		for(int i=0;i<totm;i++){
			mc.add(0,man[i].idx,1,0);
		}
		for(int i=0;i<toth;i++){
			mc.add(hou[i].idx,mc.t,1,0);
		}
		for(int i=0;i<totm;i++){
			for(int j=0;j<toth;j++){
				int d=abs(man[i].x-hou[j].x)+abs(man[i].y-hou[j].y);
				mc.add(man[i].idx,hou[j].idx,1,d);
			}
		}
		cout<<mc.Mincost()<<endl;
	}
}



Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值