题目链接: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. equals 为什么要把常量写在前面?

    看例子 使用str1.equals("abc"); 如果str1是null,空是没有equals方法的,会抛出空指针异常 如果"abc".equals(str1 ...

  2. Python标准库之logging模块

    很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误.警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,loggin ...

  3. H5_0012:js事件冒泡和捕获

    捕获(capture)和冒泡(bubble)是事件传播过程中的两个概念, 比如用户单击某个元素, 但由于元素处于父元素内, 该父元素又处于document对象中, document对象又处于windo ...

  4. 小白月赛22 G : 仓库地址

    G : 仓库地址 考察点: 二维中位数 坑点 : 做就 OK 析题得侃: 我们发现 x 和 y 是相互独立的,也就是说先移动 x 或者先移动 y 都是可以到达一个点的,所以我们可以先找到 横坐标的 中 ...

  5. HTML连载64-a标签伪类选择器的注意点与练习

    一.a标签的伪类选择器注意点 (1)a标签的伪类选择器可以单独出现,也可以一起出现.也就是可以设置多个状态的样式. (2) a标签的伪类选择器如果一起出现,那么有严格的顺序要求,编写的顺序必须要遵守原 ...

  6. java exec python program

    I find three methods, the first is using jython, the module of jython can transform the type of data ...

  7. jsonp 完成跨域请求注意事项

    jsonp 不支持post方式请求跨域数据 可以使用get方式请求 !jsonp 不支持post方式请求跨域数据 可以使用get方式请求 !jsonp 不支持post方式请求跨域数据 可以使用get方 ...

  8. ContestHunter 1201 最大子序和

    描述 输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7当m=2或m=3时,S=5+1=6 输入 ...

  9. laravel框架api路由

    Route::group(['namespace' => 'Api'], function (){ Route::any('send','SmsController@send'); }); gr ...

  10. Codeforce 567A - Lineland Mail

    All cities of Lineland are located on the Ox coordinate axis. Thus, each city is associated with its ...