题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533


解题心得:

  • 第一次写最小费用流的题,去hdoj上找了一个入门级题目,建图比较简单,用了spfa和Dij两种写法。

//spfa
#include <bits/stdc++.h>
using namespace std;
const int maxn = *; struct edge{
int to, cap, dis, rev; edge(int To, int Cap, int Dis, int Rev):
to(To), cap(Cap), dis(Dis), rev(Rev) {}
}; //感觉这里写得超级智障,懒得改了
struct men {
int x,y;
}; struct House {
int x,y;
}; vector <edge> ve[maxn];
vector <men> man;
vector <House> house;
int n, m, S, T;
char maps[maxn][maxn]; void init() {
S = ;
man.clear();
house.clear();
for(int i=;i<maxn;i++)
ve[i].clear();
for(int i=;i<=n;i++)
scanf("%s",maps[i]+);
for(int i=;i<=n;i++) {
for(int j=;j<=m;j++) {
if(maps[i][j] == 'm') {
men now;
now.x = i;
now.y = j;
man.push_back(now);
} else if(maps[i][j] == 'H') {
House temp;
temp.x = i;
temp.y = j;
house.push_back(temp);
}
}
}
T = man.size() + house.size() + ;
} void build_adge(int s, int to, int dis) {
ve[s].push_back(edge(to, , dis, ve[to].size()));
ve[to].push_back(edge(s, , -dis, ve[s].size()-));
} void add_adge() {
for(int i=;i<man.size();i++) {
build_adge(S, i+, );
for(int j=;j<house.size();j++) {
int dis = abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y);
build_adge(i+, man.size()+j+, dis);
}
}
for(int i=;i<house.size();i++) {
build_adge(i++man.size(), T, );
}
} int dist[maxn], preve[maxn], prevv[maxn];
bool vis[maxn];
bool SPFA() {
memset(preve, , sizeof(preve));
memset(vis, , sizeof(vis));
memset(prevv, , sizeof(prevv));
memset(dist, 0x3f, sizeof(dist));
dist[S] = ;
queue <int> qu;
qu.push(S);
while(!qu.empty()) {
int now = qu.front() ;qu.pop();
vis[now] = false;
for(int i=;i<ve[now].size();i++) {
edge &e = ve[now][i];
if(dist[e.to] > dist[now] + e.dis && e.cap > ) {
dist[e.to] = dist[now] + e.dis;
prevv[e.to] = now;
preve[e.to] = i;
if(!vis[e.to]) {
qu.push(e.to);
vis[e.to] = true;
}
}
}
}
return dist[T] != 0x3f3f3f3f;
} int min_cost_flow() {
int ans = ;
while(SPFA()) {
for(int v = T; v!=S ; v =prevv[v]) {
edge &e = ve[prevv[v]][preve[v]];
e.cap -= ;
ve[v][e.rev].cap += ;
ans += e.dis;
}
}
return ans;
} int main() {
while(scanf("%d%d",&n,&m) && n+m) {
init();
add_adge();
printf("%d\n",min_cost_flow());
}
return ;
}

Dij

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
const int maxn = *; struct edge{
int to, cap, dis, rev; edge(int To, int Cap, int Dis, int Rev):
to(To), cap(Cap), dis(Dis), rev(Rev) {}
}; struct men {
int x,y;
}; struct House {
int x,y;
}; vector <edge> ve[maxn];
vector <men> man;
vector <House> house;
int n, m, S, T, h[maxn];
char maps[maxn][maxn]; void init() {
S = ;
man.clear();
house.clear();
memset(h, , sizeof(h));
for(int i=;i<maxn;i++)
ve[i].clear();
for(int i=;i<=n;i++)
scanf("%s",maps[i]+);
for(int i=;i<=n;i++) {
for(int j=;j<=m;j++) {
if(maps[i][j] == 'm') {
men now;
now.x = i;
now.y = j;
man.push_back(now);
} else if(maps[i][j] == 'H') {
House temp;
temp.x = i;
temp.y = j;
house.push_back(temp);
}
}
}
T = man.size() + house.size() + ;
} void build_adge(int s, int to, int dis) {
ve[s].push_back(edge(to, , dis, ve[to].size()));
ve[to].push_back(edge(s, , -dis, ve[s].size()-));
} void add_adge() {
for(int i=;i<man.size();i++) {
build_adge(S, i+, );
for(int j=;j<house.size();j++) {
int dis = abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y);
build_adge(i+, man.size()+j+, dis);
}
}
for(int i=;i<house.size();i++) {
build_adge(i++man.size(), T, );
}
} int dist[maxn], preve[maxn], prevv[maxn];
bool Dij() {
memset(preve, , sizeof(preve));
memset(prevv, , sizeof(prevv));
memset(dist, 0x3f, sizeof(dist));
dist[S] = ;
priority_queue <P, vector<P>, greater<P> > qu;
qu.push(make_pair(,));
while(!qu.empty()) {
P now = qu.top(); qu.pop();
int pos = now.second;
if(dist[pos] < now.first)
continue;
for(int i=;i<ve[pos].size();i++) {
edge &e = ve[pos][i];
if(e.cap > && dist[e.to] > dist[pos] + e.dis + h[pos] - h[e.to]) {
dist[e.to] = dist[pos] + e.dis + h[pos] - h[e.to];
prevv[e.to] = pos;
preve[e.to] = i;
qu.push(make_pair(dist[e.to], e.to));
}
}
}
return dist[T] != 0x3f3f3f3f;
} int min_cost_flow() {
int ans = ;
while(Dij()) {
for(int i=;i<=T;i++)
h[i] += dist[i];
ans += h[T];
for(int v = T; v!=S ; v =prevv[v]) {
edge &e = ve[prevv[v]][preve[v]];
e.cap -= ;
ve[v][e.rev].cap += ;
}
}
return ans;
} int main() {
while(scanf("%d%d",&n,&m) && n+m) {
init();
add_adge();
printf("%d\n",min_cost_flow());
}
return ;
}

HDOJ:1533-Going Home(最小费用流)的更多相关文章

  1. 最大流增广路(KM算法) HDOJ 1533 Going Home

    题目传送门 /* 最小费用流:KM算法是求最大流,只要w = -w就可以了,很经典的方法 */ #include <cstdio> #include <cmath> #incl ...

  2. HDU 4067 hdoj 4067 Random Maze 最小费用流

    给出n个点,m条边,入口s和出口t,对于每条边有两个值a,b,如果保留这条边需要花费:否则,移除这条边需要花费b. 题目要求用最小费用构造一个有向图满足以下条件: 1.只有一个入口和出口 2.所有路都 ...

  3. hdu 1533 Going Home 最小费用流

    构建地图非常easy bfs预处理地图.距离的成本 来源所有m建方,流程1费0 m所有H建方,流程1距离成本 H汇点建设成为各方.流程1费0 #include<cstdio> #inclu ...

  4. hdoj 1533 Going Home 【最小费用最大流】【KM入门题】

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  5. HDOJ的题目分类

    模拟题, 枚举 1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 10 ...

  6. hdoj分类

    http://blog.csdn.net/lyy289065406/article/details/6642573 模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 ...

  7. HDOJ题目分类

    模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 104 ...

  8. HDU——PKU题目分类

    HDU 模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 ...

  9. [转] HDU 题目分类

    转载来自:http://www.cppblog.com/acronix/archive/2010/09/24/127536.aspx 分类一: 基础题:1000.1001.1004.1005.1008 ...

  10. HDU ACM 题目分类

    模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 104 ...

随机推荐

  1. Hyperledger Fabric 1.0 学习搭建 (二)--- 源码及镜像文件处理

    2.1下载Fabric源码下载Fabric源码是因为要用到源码中提到的列子和工具, 工具编译需要用到go语言环境, 因此需要把源码目录放到$GOPATH下. 通过1.3中go的安装配置, $GOPAT ...

  2. 位运算(Bit Manipulation)在算法中的应用

    最近刷LettCode,遇到几个没思路的算法题,都是关于位运算的 # 136 Single Number Given a non-empty array of integers, every elem ...

  3. February 22 2017 Week 8 Wednesday

    There is only one happiness in life, to love and be loved. 生命中只有一种幸福,爱与被爱. If you think you are not ...

  4. .net 流(Stream) - 文件流、内存流、网络流

    转自:http://www.oseye.net/user/kevin/blog/85 一.文件流 FileStream FileStream流继承与Stream类,一个FileStream类的实例实际 ...

  5. hosts配置

    转自:http://www.cnblogs.com/ylemzhang/archive/2011/10/19/2217187.htm 注意: hosts文件不支持端口映射 如果指定端口参考:  //直 ...

  6. 鉴定JavaScript中的数据类型

    众所周知,JavaScript是一门弱类型的语言,但是这并不代表JavaScript中没有数据类型.JavaScript中常见的数据类型有string.number.object等等,通常我们使用ty ...

  7. iText中输出 中文

    iText中输出中文,有三种方式: 1.使用iTextAsian.jar中的字体    BaseFont.createFont("STSong-Light", "UniG ...

  8. ios 线程同步

    https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/ThreadSafe ...

  9. c++ 基础用法、基础知识以及一些常规的操作

    1.二叉平衡树:左子树和右子树的深度差小于等于1 2.二叉搜索树:左子树小于根节点的值,右子树大于根结点的值 3.队列:push(),pop(),front(),back(),empty(),size ...

  10. bagging 和boosting的概念和区别

    1.先弄清楚模型融合中的投票的概念 分为软投票和硬投票,硬投票就是几个模型预测的哪一类最多,最终模型就预测那一类,在投票相同的情况下,投票结果会按照分类器的排序选择排在第一个的分类器结果.但硬投票有个 ...