POJ 2195 Going Home 【最小费用最大流】
题目链接:http://poj.org/problem?id=2195
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions:27150 | Accepted: 13536 |
Description
Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point.
You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.
Input
Output
题目大意:人与房子的数量相等,人每走一步花费代价为1,求所有人都进入房子的总代价最小是多少。
思路:
1.可以用KM算法,也可以用最小费用最大流。这里用最大流,KM算法在这里:https://www.cnblogs.com/yuanweidao/p/11282994.html
2.设置一个超级源点0和超级汇点 2 * n + 1, 源点向人加容量为1,费用为0的边,房子向汇点加容量为1,费用用0的边(保证费用来自人到房子的代价)。每个人与每间房子都加容量为1,费用为该人到该房子需要移动的距离与人走路代价的乘积。
(容量都为1保证跑MCMF时每条边都跑到,即每个人都到房子里去了。)
#include<stdio.h>
#include<string.h>
#include<queue>
#include<math.h>
#include<algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int MAXN = + ;
const int inf = 0x3f3f3f3f; char map[MAXN][MAXN];
int cnt1/*人的序号*/, cnt2/*房子的序号*/;
int mincost, last[ * MAXN], pre[ * MAXN], dis[ * MAXN], flow[ * MAXN], vis[ * MAXN];
queue<int> Q; struct Node
{
int x, y;
}no[ * MAXN]; struct Edge
{
int to, next, flow, cost;
}edge[ * MAXN * MAXN];
int head[ * MAXN], e_num;
void add(int a, int b, int c, int d)
{
edge[++ e_num].to = b;
edge[e_num].next = head[a];
head[a] = e_num;
edge[e_num].flow = c;
edge[e_num].cost = d;
} void init()
{
mincost = ;
cnt1 = ;
e_num = -;
mem(head, -);
} bool spfa(int st, int ed)
{
mem(dis, inf), mem(flow, inf), mem(vis, );
pre[ed] = -;
dis[st] = ;
vis[st] = ;
Q.push(st);
while(!Q.empty())
{
int now = Q.front();
Q.pop();
vis[now] = ;
for(int i = head[now]; i != -; i = edge[i].next)
{
int to = edge[i].to;
if(edge[i].flow > && dis[to] > dis[now] + edge[i].cost)
{
dis[to] = dis[now] + edge[i].cost;
pre[to] = now;
last[to] = i;
flow[to] = min(flow[now], edge[i].flow);
if(!vis[to])
{
vis[to] = ;
Q.push(to);
}
}
}
}
return pre[ed] != -;
} void MCMF()
{
while(spfa(, cnt2 + ))
{
int ed = cnt2 + ;
int now = ed;
// maxflow += flow[ed];
mincost += flow[ed] * dis[ed];
while(now != )
{
edge[last[now]].flow -= flow[ed];
edge[last[now] ^ ].flow += flow[ed];
now = pre[now];
}
}
} int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
getchar();
init();
if(n == && m == )
break;
for(int i = ; i <= n; i ++)
scanf("%s", map[i] + );
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
if(map[i][j] == 'm')
no[++ cnt1].x = i, no[cnt1].y = j; //人的编号和坐标
cnt2 = cnt1;
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
if(map[i][j] == 'H')
no[++ cnt2].x = i, no[cnt2].y = j;//房子编号和坐标
for(int i = ; i <= cnt1; i ++) //源点 0 到每个人加边 容量为1 花费为0
{
add(, i, , );
add(i, , , );
}
for(int i = cnt1 + ; i <= cnt2; i ++)//房子到 汇点 cnt2 + 1 加边 容量为1 花费为0
{
add(i, cnt2 + , , );
add(cnt2 + , i, , );
}
for(int i = ; i <= cnt1; i ++)
{
for(int j = cnt1 + ; j <= cnt2; j ++)
{
int a, b, c, d;
a = i, b = j, c = ;
d = abs(no[i].x - no[j].x) + abs(no[i].y - no[j].y);//花费为两点之间的哈密顿距离
add(a, b, c, d);
add(b, a, , -d);
}
}
MCMF();
printf("%d\n", mincost);
}
return ;
}
POJ2195
POJ 2195 Going Home 【最小费用最大流】的更多相关文章
- POJ 2195 - Going Home - [最小费用最大流][MCMF模板]
题目链接:http://poj.org/problem?id=2195 Time Limit: 1000MS Memory Limit: 65536K Description On a grid ma ...
- POJ 2195 Going Home 最小费用最大流 尼玛,心累
D - Going Home Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Subm ...
- poj 2195 Going Home(最小费用最大流)
题目:http://poj.org/problem?id=2195 有若干个人和若干个房子在一个给定网格中,每人走一个都要一定花费,每个房子只能容纳一人,现要求让所有人进入房子,且总花费最小. 构造一 ...
- poj 2351 Farm Tour (最小费用最大流)
Farm Tour Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17230 Accepted: 6647 Descri ...
- POJ 2157 Evacuation Plan [最小费用最大流][消圈算法]
---恢复内容开始--- 题意略. 这题在poj直接求最小费用会超时,但是题意也没说要求最优解. 根据线圈定理,如果一个跑完最费用流的残余网络中存在负权环,那么顺着这个负权环跑流量为1那么会得到更小的 ...
- poj 2135 Farm Tour 最小费用最大流建图跑最短路
题目链接 题意:无向图有N(N <= 1000)个节点,M(M <= 10000)条边:从节点1走到节点N再从N走回来,图中不能走同一条边,且图中可能出现重边,问最短距离之和为多少? 思路 ...
- POJ 3680: Intervals【最小费用最大流】
题目大意:你有N个开区间,每个区间有个重量wi,你要选择一些区间,使得满足:每个点被不超过K个区间覆盖的前提下,重量最大 思路:感觉是很好想的费用流,把每个区间首尾相连,费用为该区间的重量的相反数(由 ...
- POJ 2135 Farm Tour [最小费用最大流]
题意: 有n个点和m条边,让你从1出发到n再从n回到1,不要求所有点都要经过,但是每条边只能走一次.边是无向边. 问最短的行走距离多少. 一开始看这题还没搞费用流,后来搞了搞再回来看,想了想建图不是很 ...
- [poj] 1235 Farm Tour || 最小费用最大流
原题 费用流板子题. 费用流与最大流的区别就是把bfs改为spfa,dfs时把按deep搜索改成按最短路搜索即可 #include<cstdio> #include<queue> ...
- POJ 2516 Minimum Cost [最小费用最大流]
题意略: 思路: 这题比较坑的地方是把每种货物单独建图分开算就ok了. #include<stdio.h> #include<queue> #define MAXN 500 # ...
随机推荐
- select([[data],fn])
select([[data],fn]) 概述 当 textarea 或文本类型的 input 元素中的文本被选择时,会发生 select 事件.大理石平台生产厂 这个函数会调用执行绑定到select事 ...
- 国庆集训Day1
T1 divide 题意: 有\(n\)个数 \(a_1, a_2,..., a_n\) 有m个数\(b_1, b_2,..., b_n\) 令\(a = a_1\times a_2\,\times ...
- MySQL数据分析-(15)表补充:存储引擎
大家好,我是jacky,很高兴继续跟大家分享<MySQL数据分析实战>,今天跟大家分享的主题是表补充之存储引擎: 我们之前学了跟表结构相关的一些操作,那我们看一下创建表的SQL模型: 在我 ...
- 常用SQL之日期格式化和查询重复数据
本文列举一些工作中常用的SQL,以提升工作效率. 1 日期格式化 使用 DATE_FORMAT(get_date, '%Y-%m-%d') 函数进行格式化.其中:get_date 是需要被格式化的字段 ...
- Maven的安装和配置(Windows 10)
1. 官网下载Maven管理工具 官网:https://maven.apache.org/download.cgi 系统要求: JDK:Maven 3.3以上需要JDK 1.7以上版本支持 Memor ...
- JAVA基于File的基本的增删改查
直接上代码 public class TestFile { /** * 创建目录 * @param filename 路径 */ public static void createFile(Strin ...
- 安装Mysql-5.7.13脚本
安装Mysql-5.7.13,此脚本最后会查找到临时密码,后面登进数据库中更改密码 [root@ZHONG-LONG javascripts]# vim -mysql.sh #!/bin/bash # ...
- jQuery源码解读----part 2
分离构造器 通过new操作符构建一个对象,一般经过四步: A.创建一个新对象 B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象) C.执行构造函数中的代码 D.返回这个新对象 最后一点 ...
- mysql密码设置为空怎么办?
由于很多童鞋安装使用MySQL时,安装时没有设置密码,或者像我一样图省事设置密码为空,想为其设置新密码: 1.点击 开始------>运行----在弹出的对话框中输入cmd 如下图: 2.使用 ...
- 阶段5 3.微服务项目【学成在线】_day04 页面静态化_03-freemarker测试环境搭建
新建一个module 选择parent test-freemarker spring‐boot‐starter‐freemarker:spring boot 提供的关于 freemaker的相关的包 ...