poj_2195Going Home(最小费用最大流)
poj_2195Going Home(最小费用最大流)
标签: 最小费用最大流
题意:
有n*m的矩阵,H表示这个点是一个房子,m表示这个点是一个人,现在每一个人需要走入一个房间,已经知道的是认得数目和房子的个数一定是相同的,现在问这些人都回到一个房间所走的总的步数最小
题解:
这个题是一个很典型的最小费用最大流的模板题,建图也很容易想到,就是增加一个新的源点和汇点,从源点到每一个人建一条流量为1,费用为0的边,每个房子到汇点也建立一条流量为1,费用为0的边,每个人都与所有的房子建立费用为两者距离,流量为1的边,然后求一遍最小费用最大流即可。
算法介绍:
我们知道最大流是通过每次寻找增广路来求解的,而现在要在保证最大流的情况下让费用最小,那就可以每次寻找增广路的时候用SPFA找满足增广路条件,即可增广,的情况下的最短路,然后对这条路径进行增广,然后更新残留网络,然后再找最短路,直到找不到了为止。
这种题理解了实现的原理,然后直接套用模板即可
最小费用最大流模板
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
#define V 60100
#define E 1000100
#define inf 99999999
using namespace std;
int vis[V];
int dist[V];
int pre[V];
int Abs(int a){
if(a<0) return 0-a;
else return a;
}
struct Edge{
int u,v,c,cost,next;
}edge[E];
int head[V],cnt;
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c,int cost)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].cost=cost;
edge[cnt].c=c;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].u=v;
edge[cnt].v=u;
edge[cnt].cost=-cost;
edge[cnt].c=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
bool spfa(int begin,int end){
int u,v;
queue<int> q;
for(int i=0;i<=end+2;i++){
pre[i]=-1;
vis[i]=0;
dist[i]=inf;
}
vis[begin]=1;
dist[begin]=0;
q.push(begin);
while(!q.empty()){
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next){
if(edge[i].c>0){
v=edge[i].v;
if(dist[v]>dist[u]+edge[i].cost){
dist[v]=dist[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
}
return dist[end]!=inf;
}
int MCMF(int begin,int end){
int ans=0,flow;
int flow_sum=0;
while(spfa(begin,end)){
flow=inf;
for(int i=pre[end];i!=-1;i=pre[edge[i].u])
if(edge[i].c<flow)
flow=flow,edge[i].c;
for(int i=pre[end];i!=-1;i=pre[edge[i].u]){
edge[i].c-=flow;
edge[i^1].c+=flow;
}
ans+=dist[end];
flow_sum += flow;
}
//cout << flow_sum << endl;
return ans;
}
下面是这个题的ac代码
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
#define V 60100
#define E 1000100
#define inf 99999999
using namespace std;
int vis[V];
int dist[V];
int pre[V];
int Abs(int a){
if(a<0) return 0-a;
else return a;
}
struct Edge{
int u,v,c,cost,next;
}edge[E];
int head[V],cnt;
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c,int cost)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].cost=cost;
edge[cnt].c=c;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].u=v;
edge[cnt].v=u;
edge[cnt].cost=-cost;
edge[cnt].c=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
bool spfa(int begin,int end){
int u,v;
queue<int> q;
for(int i=0;i<=end+2;i++){
pre[i]=-1;
vis[i]=0;
dist[i]=inf;
}
vis[begin]=1;
dist[begin]=0;
q.push(begin);
while(!q.empty()){
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next){
if(edge[i].c>0){
v=edge[i].v;
if(dist[v]>dist[u]+edge[i].cost){
dist[v]=dist[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
}
return dist[end]!=inf;
}
int MCMF(int begin,int end){
int ans=0,flow;
int flow_sum=0;
while(spfa(begin,end)){
flow=inf;
for(int i=pre[end];i!=-1;i=pre[edge[i].u])
if(edge[i].c<flow)
flow=flow,edge[i].c;
for(int i=pre[end];i!=-1;i=pre[edge[i].u]){
edge[i].c-=flow;
edge[i^1].c+=flow;
}
ans+=dist[end];
flow_sum += flow;
}
//cout << flow_sum << endl;
return ans;
}
char mp[202][202];
int HH[V];
int HL[V];
int MH[V];
int ML[V];
int S,T;
int cm,ch;
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m),n+m)
{
init();
getchar();
for(int i = 0; i < n; i++){
gets(mp[i]);
}
cm = ch = 1;
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
//printf("%c ",mp[i][j]);
if(mp[i][j]=='H'){
HH[ch] = i;
HL[ch++] = j;
}
else if(mp[i][j]=='m'){
MH[cm] = i;
ML[cm++] = j;
}
}
}
cm--;
ch--;
S = 0;
T = cm+ch+1;
for(int i = 1; i <= cm; i++){
addedge(S,i,1,0);
}
for(int i = 1; i <= ch; i++){
addedge(cm+i,T,1,0);
}
for(int i = 1; i <= cm; i++){
for(int j = 1; j <= ch; j++){
int tm = Abs(HH[j]-MH[i])+Abs(HL[j]-ML[i]);
//printf("(%d,%d)-(%d,%d),tm = %d\n",HH[j],HL[j],MH[i],ML[i],tm);
addedge(i,cm+j,1,tm);
//printf("(%d,%d)",i,j);
}
}
int ans = MCMF(S,T);
printf("%d\n",ans);
}
return 0;
}
poj_2195Going Home(最小费用最大流)的更多相关文章
- [板子]最小费用最大流(Dijkstra增广)
最小费用最大流板子,没有压行.利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多.教程略去.转载请随意. #include <cstdio> #incl ...
- bzoj1927最小费用最大流
其实本来打算做最小费用最大流的题目前先来点模板题的,,,结果看到这道题二话不说(之前打太多了)敲了一个dinic,快写完了发现不对 我当时就这表情→ =_=你TM逗我 刚要删突然感觉dinic的模 ...
- ACM/ICPC 之 卡卡的矩阵旅行-最小费用最大流(可做模板)(POJ3422)
将每个点拆分成原点A与伪点B,A->B有两条单向路(邻接表实现时需要建立一条反向的空边,并保证环路费用和为0),一条残留容量为1,费用为本身的负值(便于计算最短路),另一条残留容量+∞,费用为0 ...
- HDU5900 QSC and Master(区间DP + 最小费用最大流)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...
- P3381 【模板】最小费用最大流
P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行 ...
- 【BZOJ-3876】支线剧情 有上下界的网络流(有下界有源有汇最小费用最大流)
3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 821 Solved: 502[Submit][Status ...
- hdu 4411 2012杭州赛区网络赛 最小费用最大流 ***
题意: 有 n+1 个城市编号 0..n,有 m 条无向边,在 0 城市有个警察总部,最多可以派出 k 个逮捕队伍,在1..n 每个城市有一个犯罪团伙, 每个逮捕队伍在每个城市可以选 ...
- UVa11082 Matrix Decompressing(最小费用最大流)
题目大概有一个n*m的矩阵,已知各行所有数的和的前缀和和各列所有数的和的前缀和,且矩阵各个数都在1到20的范围内,求该矩阵的一个可能的情况. POJ2396的弱化版本吧..建图的关键在于: 把行.列看 ...
- UVa12092 Paint the Roads(最小费用最大流)
题目大概说一个n个点m条带权有向边的图,要给边染色,染色的边形成若干个回路且每个点都恰好属于其中k个回路.问最少要染多少边权和的路. 一个回路里面各个点的入度=出度=1,那么可以猜想知道各个点如果都恰 ...
随机推荐
- c语言项目流程开发三部曲
一.这一部曲是紧接第二部没有介绍完的内容,主要是函数接口实体的实现,代码比较多,如果没有看前两部曲的先去看看,再来看这里,不然不好理解,话不说多上代码, #define _CRT_SECURE_NO_ ...
- 编译c语言程序扩展ruby
环境: windows 10 64bit ruby 2.2.4p230 (2015-12-16 revision 53155) [i386-mingw32] gcc version 4.8.1 (GC ...
- WPF后台写ControlTemplate总结
这段时间写ControlTemplate的时候发现绑定的时候有些问题需要总结: 实例ControlTemplate如下: <UserControl x:Class="ArcGISWpf ...
- linux系统下phpstudy里的mysql使用方法
linux作为一个优秀的服务器端管理系统,其实linux的桌面系统也用起来十分的nice.好吧,如何你在做开发的时候在linux下安装了lmap或者phpstudy,那么在第一次使用其自带的mysql ...
- java inputstream to string stack overflow
https://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string 过千赞的答案
- C# DataGridView 列的显示顺序
this.dataGridView1.Columns["列名"].DisplayIndex=Convert.ToInt32("你要放置的位置")
- ubuntu更换阿里源
网上应该可以找到很多关于ubuntu源的设置方法,但是如果不搞清楚就随便设置的话,不仅不能起到应有的效果,还会由于一些问题导致apt不可用. 最正确的更换源的方法应该如系统提示的: ## a.) ad ...
- Vue-cli 创建的项目如何跨域请求
感谢BeArchitect的技术支持 问题描述: 使用 Vue-cli 创建的项目,开发地址是 localhost:8023,需要访问 localhost:9000 上的接口 分析原因: 不同域名之间 ...
- RobotFrame连接MySql数据库
RobotFrame连接MySql数据库这类的教程网上并不多,就算有,也是很多坑.小编今天为大家提供一个靠谱的教程,但是具体的包需要大家自己下载.废话不多说,看疗效~~~ 1.pip install ...
- Hive安装与配置详解
既然是详解,那么我们就不能只知道怎么安装hive了,下面从hive的基本说起,如果你了解了,那么请直接移步安装与配置 hive是什么 hive安装和配置 hive的测试 hive 这里简单说明一下,好 ...