题目链接: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. kivy.org - Open source Python library for rapid development of applications

    kivy.org - Open source Python library for rapid development of applicationsthat make use of innovati ...

  2. C与C++混编

    了解一下C与C++如何合作,gcc和g++编译出来的东西有什么区别. 工具使用 objdump是个好工具,可以用于查看.o文件的内容,也可以查看可执行文件的内容. 查看符号表 objdump -t f ...

  3. 不错的.net开源项目

    Json.NET http://json.codeplex.com/ Json.Net是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单.通过Lin ...

  4. monodevelop 基础用法

    1.mono快捷键      CTRL+K  删除光标所在行的该行后面的代码 CTRL + ALT +C  注释/不注释该行 CTRL+ DOWN  像鼠标滚轮一样向下拖 CTRL + UP 像鼠标滚 ...

  5. mongoDB 固定集合(capped collection)

    固定集合(Capped Collection)是一种尺寸固定的“循环”集合,可提供高效的创建.读取.删除等操作.这里所指的“循环”的意思是,当分配给集合的文件尺寸耗尽时,就会自动开始删除最初的文档,不 ...

  6. DispatcherServlet类的分析

    突然发现拿博客园来做笔记挺好的,不会弄丢.下面我把DispatcherServlet类的部分源代码复制到这里,然后阅读,把重要的地方翻译一下,该做笔记的地方做下笔记,蹩脚英语. =========== ...

  7. bzoj1434 [ZJOI2009]染色游戏

    Description 一共n × m 个硬币,摆成n × m 的长方形.dongdong 和xixi 玩一个游戏, 每次可以选择一个连通块,并把其中的硬币全部翻转,但是需要满足存在一个 硬币属于这个 ...

  8. PHP---练习-----留言板

    题目::留言显示 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...

  9. thinkPHP输出sql语句(3.2和5.0通用)

    //5.0$qwe = db::table('think_user')->where('id',1)->fetchsql()->column('name'); dump($qwe); ...

  10. easyui分页的使用方法

    使用: $("#tt").datagrid("getPager").pagination(option); 例子: $("#tb").dat ...