题目链接:http://poj.org/problem?id=2195

题目大意是给一张网格,网格中m代表人,h代表房子,网格中的房子和人数量相等,人可以向上向下走,每走1步花费加1,每个房子只能住一个人,问使得所有人住房子里最少的花费是多少?

最小费用流的题目,最大流跑spfa,每个人和每个房子之间建边,边的流量为1,花费是人到房子的距离,假定一个源点和一个汇点,源点连接所有的人,每条边流量为1,花费为0,所有的房子连接汇点,同样的边流量是1,花费是0,从源点到汇点跑一下费用流就可以得出答案。其中每个人到每个房子的距离d = 纵坐标的差值绝对值+横坐标的差值绝对值。图很好建,细节注意一下,多组数据记得初始化。

AC代码:

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
struct node{
vector<int> vex;//g[i]连接的点集
vector<int> num;//g[i]连接的边集
}g[205];
struct edge{
int u,v,c,cost;//u起点,v终点,c流量 cost花费
}e[205*205];
vector<pair<int,int> > Vmen;//存储人的坐标
vector<pair<int,int> > Vh;//存储房子的坐标
int men = 0,h = 0;//人和房子的个数
int sp,tp;//源点汇点
int inq[205],d[205],pre[205];
int cal(int a,int b){// a为人,b为房子 first横坐标,second纵坐标
return abs(Vmen[a].first - Vh[b].first)+abs(Vmen[a].second - Vh[b].second);
}
int edgenum ;//边的序号从0开始,
void addedge(int u,int v,int c,int cost){
e[edgenum].u = u,e[edgenum].v = v;
e[edgenum].c = c,e[edgenum].cost = cost;
g[u].vex.push_back(v),g[u].num.push_back(edgenum++);
// 建立双向边操作
e[edgenum].u = v,e[edgenum].v = u;
e[edgenum].c = 0,e[edgenum].cost = -cost;
g[v].num.push_back(edgenum++),g[v].vex.push_back(u);
}
bool spfa(int s,int t){
for(int i = 0;i<205;i++){
inq[i] = 0;//是否在队列
d[i] = inf;//记录最小花费
pre[i] = -1;//初始化-1
}//初始化
d[s] = 0,inq[s] = 1;
queue<int> q;
q.push(s);
while(!q.empty()){
int now = q.front() ;
q.pop() ;
inq[now] = 0;
for(int i = 0;i<g[now].num.size() ;i++ ){
int te = g[now].num[i];
int tv = g[now].vex[i];
if(e[te].c >0 && d[tv] > d[now] + e[te].cost ){
d[tv] = d[now] + e[te].cost ;
pre[tv] = te;//存储以tv为后继节点的边集 该边te : now->tv
if(!inq[tv]){
inq[tv] = 1;
q.push(tv);
}
}
}
}
return d[tp]!=inf; //找不到增广路就返回false
}
int mincostmaxflow(int s,int t){
int ans_cost = 0, u,minCut;
while(spfa(s,t)){
minCut = inf;
for(u = pre[t];u!=-1;u = pre[e[u].u]){
if(minCut > e[u].c ){
minCut = e[u].c ;
}
}
for(u = pre[t];u!=-1;u = pre[e[u].u]){
e[u^1].c+=minCut;//双向边做加和该增广路最大流操作
e[u].c-=minCut;
}
ans_cost+=minCut*d[tp];
}
return ans_cost;
}
vector<string> map;
int main(){
int n,m;
while(cin>>n>>m){
if(!n&&!m){
return 0;
}
edgenum = 0,map.clear(),Vmen.clear(),Vh.clear(),men = 0,h = 0;//初始化数据
for(int i = 0;i<205;i++){
g[i].num.clear();
g[i].vex.clear();
}//初始化数据
for(int i = 0;i<n;i++){
string t;
cin>>t;
map.push_back(t);
}
for(int i = 0;i<map.size();i++){
for(int j = 0;j<m;j++){
if(map[i][j] == 'H'){
h++;
Vh.push_back(make_pair(i,j));
}
if(map[i][j] == 'm'){
men++;
Vmen.push_back(make_pair(i,j));
}
}
}
sp = 0;
tp = men+h+1;
for(int i = 1;i<=men;i++){
addedge(sp,i,1,0);
}
for(int i = men+1;i<=2*men;i++){
addedge(i,tp,1,0);
}
for(int i = 0;i<Vmen.size() ;i++){
for(int j = 0;j<Vh.size() ;j++){
int cost = cal(i,j);
addedge(i+1,men+j+1,1,cost);
}
}
cout<<mincostmaxflow(sp,tp)<<endl;
}
return 0;
}

poj 2195 Going Home(最小费用流)的更多相关文章

  1. POJ 2195 Going Home 最小费用流 裸题

    给出一个n*m的图,其中m是人,H是房子,.是空地,满足人的个数等于房子数. 现在让每个人都选择一个房子住,每个人只能住一间,每一间只能住一个人. 每个人可以向4个方向移动,每移动一步需要1$,问所有 ...

  2. POJ 2195 Going Home 最小费用流 难度:1

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17955   Accepted: 9145 Descr ...

  3. POJ 2195 Going Home 最小费用流

    POJ2195 裸的最小费用流,当然也可以用KM算法解决,但是比较难写. 注意反向边的距离为正向边的相反数(因此要用SPFA) #include<iostream> #include< ...

  4. POJ 2195 Going Home 最小费用最大流 尼玛,心累

    D - Going Home Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Subm ...

  5. poj 2195 二分图带权匹配+最小费用最大流

    题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...

  6. POJ 2195 Going Home / HDU 1533(最小费用最大流模板)

    题目大意: 有一个最大是100 * 100 的网格图,上面有 s 个 房子和人,人每移动一个格子花费1的代价,求最小代价让所有的人都进入一个房子.每个房子只能进入一个人. 算法讨论: 注意是KM 和 ...

  7. POJ 2195 Going Home (带权二分图匹配)

    POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...

  8. poj 2195 Going Home(最小费最大流)

    poj 2195 Going Home Description On a grid map there are n little men and n houses. In each unit time ...

  9. 【POJ 2195】 Going Home(KM算法求最小权匹配)

    [POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

随机推荐

  1. Android View框架的draw机制

    概述 Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure) Android View框架的measure机制 2.View树的布局(layout)Andr ...

  2. 在ASP.NET 中调用 WebService 服务

    一.webservice定义 详见 https://www.cnblogs.com/phoebes/p/8029464.html 二.在ASP.NET MVC 中调用 webservice 1:要调用 ...

  3. Yeoman+Bower+gulp web前端自动化工作流程(初级教程)

    Yeoman包括了三个部分yo(脚手架工具).grunt/gulp(构建工具).bower(包管理器).听说gulp更容易上手,所以我就没用grunt而选的gulp 什么是开发流程? 在我看来一个完整 ...

  4. 曼孚科技:AI机器学习领域常用的15个术语

    机器学习是人工智能(AI)的核心,是使计算机具有智能的根本途径.​ 本文整理了一下机器学习领域常用的15个术语,希望可以帮助大家更好的理解这门涉及概率论.统计学.逼近论.凸分析.算法复杂度理论等多个领 ...

  5. C++-POJ3070-Fibonacci-[矩阵乘法][快速幂]

    #include <cstdio> ][];}; ,MOD=1e4; Matrix A,B,O,I; Matrix Mul(Matrix A,Matrix B){ Matrix C=O; ...

  6. navicat异常 - 1130-host ... is not allowed to connect to this MySql server

    错误描述 用navicat连接数据库报错:1130-host ... is not allowed to connect to this MySql server如何处理 解决方案 1.连接服务器: ...

  7. SDOI2010 粟粟的书架 lg2468(可持久化,前缀和)

    题面见https://www.luogu.org/problemnew/show/P2468 然后这道题属于合二为一题,看一眼数据范围就能发现 首先我们先考虑50分,二维前缀和维护一下(反正我不记得公 ...

  8. RN开发-IDE和API

    一.开发工具 1.Visual Studio Code:微软IDE,轻量级,只有30+M大小 2.nuclide :仅支持Mac 3.WebStorm : JavaScript开发工具(IDE) 二. ...

  9. vscode里的NPM脚本

    NPM脚本的开启与关闭 点击设置-功能-任务 控制为所有任务提供程序扩展启用"提供任务".如果"任务:运行任务"命令速度较慢,则禁用任务提供程序的自动检测可能会 ...

  10. linux centos7环境下安装apache2.4+php5.6+mysql5.6 安装及踩坑集锦(二)

    linux centos7环境下安装apache2.4+php5.6+mysql5.6 安装及踩坑集锦(二) 安装apache web容器 . yum方式安装apache 注意apache在linux ...