最小费用最大流,即MCMF(Minimum Cost Maximum Flow)问题

嗯~第一次写费用流题。。。

这道就是费用流的模板题,找不到更裸的题了

建图:每个m(Man)作为源点,每个H(House)作为汇点,各个源点与汇点分别连一条边,这条边的流量是1(因为每个源点只能走一条边到汇点),费用是 从源点走到汇点的步数,因为有多个源点与汇点,要建一个超级源点与超级汇点,超级源点与各个源点连一条流量为1,费用为0(要避免产生多余的费用)的边

按照这个图跑一发费用流即可


关于模板:前向星+SPFA

初始化注意:size 表示网络中的结点数,编号从0开始,如果是从1开始则size=n+1,其他的,head全设为-1,Edge为边数预先设为0

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define MAXN 3000
#define MAXM 50000
#define INF (1<<30)
#define eps 0.000001
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
using namespace std;
int i,j,k,n,m,x,y,T,num,w,Man,House,hou[305][2],man[305][2]; /*最小费用流模板 -BEGIN-*/
/*size表示网络中的结点数,编号从0开始,如果是从1开始则size=n+1*/
/*初始化:head全设为-1,Edge为边数预先设为0*/
int head[MAXN],vis[MAXN],dis[MAXN],pos[MAXN],Edge,size;
char s[305][305];
struct edgenode
{
int to,next,w,cost;
} edge[MAXM]; void add_edge(int x,int y,int w,int cost)
{
edge[Edge].to=y;
edge[Edge].w=w;
edge[Edge].cost=cost;
edge[Edge].next=head[x];
head[x]=Edge;
Edge++; edge[Edge].to=x;
edge[Edge].w=0;
edge[Edge].cost=-cost;
edge[Edge].next=head[y];
head[y]=Edge;
Edge++;
} bool SPFA(int s, int t)
{
int u,v,i;
queue <int> q;
memset(vis,0,sizeof(vis));
for(i=0;i<size;i++) dis[i]=INF;
dis[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty())
{
u=q.front(); q.pop(); vis[u]=0;
for (i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(edge[i].w>0&&dis[u]+edge[i].cost<dis[v])
{
dis[v]=dis[u]+edge[i].cost;
pos[v]=i;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
return dis[t]!=INF;
}
int MinCostFlow(int s,int t)
{
int i,cost=0,flow=0;
while(SPFA(s,t))
{
int d=INF;
for (i=t;i!=s;i=edge[pos[i]^1].to)
{
d=min(d,edge[pos[i]].w);
}
for(i=t;i!=s;i=edge[pos[i]^1].to)
{
edge[pos[i]].w-=d;
edge[pos[i]^1].w+=d;
}
flow+=d;
cost+=dis[t]*d;
}
return cost; // flow是最大流值
}
/*最小费用流模板 -END-*/
int main()
{
while(scanf("%d%d",&n,&m),n+m)
{
memset(head,-1,sizeof(head));
Edge=Man=House=num=0;
for (i=0;i<n;i++) scanf("%s",s[i]);
for (i=0;i<n;i++)
{
for (j=0;j<m;j++)
{
if (s[i][j]=='m')
{
Man++;
man[Man][0]=i;
man[Man][1]=j;
}else
if (s[i][j]=='H')
{
House++;
hou[House][0]=i;
hou[House][1]=j;
}
}
}
size=Man+House+2;
/*超级源点0,到各个人的边*/
for (i=1;i<=Man;i++)
{
add_edge(0,i,1,0);
}
/*各源点与各汇点之间的边*/
for (i=1;i<=Man;i++)
{
for (j=1;j<=House;j++)
{
add_edge(i,Man+j,1,abs(man[i][0]-hou[j][0])+abs(man[i][1]-hou[j][1]));
}
}
/*超级汇点0,到各个人的边*/
for (i=1;i<=House;i++)
{
add_edge(Man+i,Man+House+1,1,0);
}
printf("%d\n",MinCostFlow(0,Man+House+1));
}
return 0;
}

  

据说可以用KM算法来写,下次补上KM算法的代码。。。

【网络流#2】hdu 1533 - 最小费用最大流模板题的更多相关文章

  1. hdu 1533(最小费用最大流)

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

  2. POJ2135 最小费用最大流模板题

    练练最小费用最大流 此外此题也是一经典图论题 题意:找出两条从s到t的不同的路径,距离最短. 要注意:这里是无向边,要变成两条有向边 #include <cstdio> #include ...

  3. 2018牛客网暑期ACM多校训练营(第五场) E - room - [最小费用最大流模板题]

    题目链接:https://www.nowcoder.com/acm/contest/143/E 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...

  4. HDU 1533 最小费用最大流(模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 这道题直接用了模板 题意:要构建一个二分图,家对应人,连线的权值就是最短距离,求最小费用 要注意void ...

  5. HDU3376 最小费用最大流 模板2

    Matrix Again Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)To ...

  6. 最大流 && 最小费用最大流模板

    模板从  这里   搬运,链接博客还有很多网络流题集题解参考. 最大流模板 ( 可处理重边 ) ; const int INF = 0x3f3f3f3f; struct Edge { int from ...

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

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

  8. 洛谷P3381 最小费用最大流模板

    https://www.luogu.org/problem/P3381 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用 ...

  9. hdu 1533 Going Home 最小费用最大流 入门题

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

随机推荐

  1. uva 11673 Garbage Remembering Exam (概率)

    题目链接: http://vjudge.net/problem/viewProblem.action?id=42000 该过程为随即过程,因此总期望值等于个单词对应的期望值,即它们wasted的概率 ...

  2. [转]python集合set

    Python中集合set是基本数据类型的一种,它有可变集合(set)和不可变集合(frozenset)两种.创建集合set.集合set添加.集合删除.交集.并集.差集的操作都是非常实用的方法. 来源网 ...

  3. 3.5 linux 0.11 目标文件格式

    在Linux0.11系统中,GNU gcc或gas编译输出的目标模块文件和链接程序生成的可执行文件都使用了UNIX传统的a.out格式.这是一种被称为汇编与链接输出(Assembly & li ...

  4. CRM窗体中只读的控件不会引发Update事件

    在CRM的窗体设计时,如果把某一个控件设为只读了,仅管你在后台用代码修改了值,这个值也不会起任何作用,更不会提交到后台,触发Update事件!

  5. Js屏蔽键盘事件

    <script>           function KeyDown(){ //屏蔽鼠标右键.Ctrl+n.shift+F10.F5刷新.退格键            //alert(& ...

  6. DIV+CSS两种盒子模型

    盒子模型有两种,分别是 IE 盒子模型和标准 W3C 盒子模型.他们对盒子模型的解释各不相同, 先来看看我们熟悉的标准盒子模型: 从上图可以看到标准 W3C 盒子模型的范围包括 margin.bord ...

  7. 运维小东西:每天备份sql到远程服务器上

    首先两台服务器可以无密码登录(这个方式比较简单,当然安全系数会降低) #ssh-keygen -t rsa #生成密钥发送给远程服务器上 #ssh-copy-id ~/root/id_rsa.pub ...

  8. poj 3371 Flesch Reading Ease

    http://poj.org/problem?id=3371 #include<cstdio> #include<cstring> #include<algorithm& ...

  9. 为什么 O2O 领域融资额特别高?

    在36氪搜索“o2o”,融资额基本都是数千万乃至数亿,为什么这个领域的创业项目融资额如此之高?融到的钱一般用在什么地方? --------------------------------------- ...

  10. Delphi——Window 消息 - 转载▼

    Delphi是Borland公司的一种面向对象的可视化软件开发工具. Delphi集中了Visual C++和Visual Basic两者的优点:容易上手.功能强大,特别是在界面设计.数据库编程.网络 ...