#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
#define N 205
#define INF 0x3f3f3f3f
struct node {
int x, y;
node () {}
node (int x, int y) : x(x), y(y) {}
};
struct Edge {
int cap, u, v, cost;
Edge() {}
Edge(int u, int v, int cap, int cost) : u(u), v(v), cap(cap), cost(cost) {}
}edge[N*N];
vector<node> p, h;
vector<int> G[N];
int tot, dis[N], inq[N], pre[N], S, T; void AddEdge(int u, int v, int cap, int cost) {
edge[tot] = Edge(u, v, cap, cost);
G[u].push_back(tot++);
edge[tot] = Edge(v, u, , -cost);
G[v].push_back(tot++);
} int CalDis(int x1, int y1, int x2, int y2) {
return abs(x1 - x2) + abs(y1 - y2);
} bool SPFA() {
memset(inq, , sizeof(inq));
memset(dis, INF, sizeof(dis));
queue<int> que; que.push(S);
dis[S] = ; inq[S] = ;
while(!que.empty()) {
int u = que.front(); que.pop(); inq[u] = ;
for(int i = ; i < G[u].size(); i++) {
Edge &e = edge[G[u][i]];
if(e.cap > && dis[e.v] > e.cost + dis[u]) {
// 当可以增广并且费用更小的时候
dis[e.v] = e.cost + dis[u];
pre[e.v] = G[u][i]; // 记录路径
if(inq[e.v]) continue;
que.push(e.v); inq[e.v] = ;
}
}
}
return dis[T] < INF;
} void MFMC(int &mincost, int &maxflow) {
int ans = , flow = INF, p;
// 从汇点沿着此次增广的路径往回走,当找到源点的时候退出
for(int u = T; u; u = edge[p].u) {
p = pre[u]; // 找增广的流量
if(edge[p].cap < flow) flow = edge[p].cap;
}
for(int u = T; u; u = edge[p].u) {
p = pre[u];
edge[p].cap -= flow; // 更新每条边的流量
edge[p^].cap += flow;
ans += flow * edge[p].cost; // 费用 = 单位费用 * 流量
}
mincost += ans, maxflow += flow;
} int main() {
int n, m;
char s[];
while(scanf("%d%d", &n, &m), n + m) {
p.clear(); h.clear();
for(int i = ; i < n; i++) {
scanf("%s", s);
for(int j = ; j < m; j++) {
if(s[j] == 'H') h.push_back(node(i, j));
if(s[j] == 'm') p.push_back(node(i, j));
}
}
tot = ; int sz1 = p.size(), sz2 = h.size();
S = , T = sz1 + sz2 + ;
for(int i = ; i <= T; i++) G[i].clear();
for(int i = ; i < sz1; i++) // S到man
AddEdge(S, i + , , );
for(int i = ; i < sz2; i++) // house到T
AddEdge(i + + sz1, T, , );
for(int i = ; i < sz1; i++) {
for(int j = ; j < sz2; j++) {
int c = CalDis(p[i].x, p[i].y, h[j].x, h[j].y);
AddEdge(i + , j + + sz1, , c);
}
} int mincost = , maxflow = ;
while(SPFA()) MFMC(mincost, maxflow);
printf("%d\n", mincost);
}
return ;
}

连续最短路算法(Successive Shortest Path)(最小费用最大流)的更多相关文章

  1. SGU 185.Two shortest (最小费用最大流)

    时间限制:0.25s 空间限制:4M 题意: 在n(n<=400)个点的图中,找到并输出两条不想交的最短路.不存在输出“No sulotion”: Solution: 最小费用最大流 建图与po ...

  2. TZOJ 4712 Double Shortest Paths(最小费用最大流)

    描述 Alice and Bob are walking in an ancient maze with a lot of caves and one-way passages connecting ...

  3. SGU185 Two shortest(最小费用最大流/最大流)

    题目求一张图两条边不重复的最短路. 一开始我用费用流做. 源点到1连容量2费用0的边:所有边,连u到v和v到u容量1费用cost的边. 总共最多会增广两次,比较两次求得的费用,然后输出路径. 然而死M ...

  4. 图论算法-最小费用最大流模板【EK;Dinic】

    图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...

  5. 算法笔记--最大流和最小割 && 最小费用最大流 && 上下界网络流

    最大流: 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow). 最小割: 割是网 ...

  6. 经典贪心算法(哈夫曼算法,Dijstra单源最短路径算法,最小费用最大流)

    哈夫曼编码与哈夫曼算法 哈弗曼编码的目的是,如何用更短的bit来编码数据. 通过变长编码压缩编码长度.我们知道普通的编码都是定长的,比如常用的ASCII编码,每个字符都是8个bit.但在很多情况下,数 ...

  7. hdu 3395(KM算法||最小费用最大流(第二种超级巧妙))

    Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  8. hdu 3488(KM算法||最小费用最大流)

    Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submis ...

  9. hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙

    /** 题目:hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4106 ...

  10. POJ 3680 Intervals 最小费用最大流(MCMF算法)

    题意:给出 n ,k 表示接下来给你 n 段开区间,每段区间都有它的权值,问选出一些区间,使它的权值最大,并且在实轴上的每个点,不得超过 k次被覆盖. 思路:首先要理解建图思路,首先有一个基图,相邻点 ...

随机推荐

  1. maven pom文件结构详解

    POM文件结构 Project Object Model是Maven2项目的基础所在,简单来说它就是一个XML文件,Maven2用它来描述一个工程的整个生命周期所需要执行的一系列功能和特性. 最小配置 ...

  2. wxpython更新

    .configure时候检查不到gtk+ 使用 apt-get install gnome-core-devel

  3. springmvc源码分析

    Spring MVC源码分析--初始化过程 标签: springmvcconstructioniocclass 2012-09-09 21:32 26578人阅读 评论(3) 收藏 举报 版权声明:本 ...

  4. # 20145334赵文豪 《Java程序设计》第5周学习总结

    20145334赵文豪 <Java程序设计>第5周学习总结 教材学习内容总结 第八章 1.使用try.catch打包System.in.read(),声明throws java.io.IO ...

  5. vim的常用命令

    平常最多是用vim来编辑单个文件,看看源码.就是写几k行代码时也没有用一些其他的插件,只是设置了高亮等一些自带的属性.这样的好处是,换到任何一台新机上都能立马使用. 网上流传了大量的“vim命令合集” ...

  6. javac编译、运行

    java源码(包结构) 源码存放位置:C:/Users/liaolongjun/DeskTop/java/ package test; import test.sub.F; public class ...

  7. Java 隐藏和覆盖

    我们知道,在JAVA中,子类可以继承父类,如果子类声明的方法与父类有重名的情况怎么办,大伙儿都知道要是重写,但是实际上这又分为两种情况,就是方法和变量在继承时的覆盖和隐藏问题,这些概念性的东西看似无聊 ...

  8. 一个相比jdk的io包更方便处理数据读写的包

    apche的commons-io.jar包,里面有个类IOUtils,提供的下列方法: readLines方法能够从字节输入流或字符输入流里读取数据,按行读,返回字符串组成的list write方法能 ...

  9. java中获取日期和时间的方法总结

    1.获取当前时间,和某个时间进行比较.此时主要拿long型的时间值. 方法如下:  要使用 java.util.Date .获取当前时间的代码如下 Date date = new Date(); da ...

  10. cocos2d-x mac os启动 android helloworld

    工具环境: mac os, jdk, Android Studio, cocos2d-x-3.13.1, ant, android-ndk. 解压coco2d-x后,根目录下有 setup.py, 命 ...