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 # ...
随机推荐
- P4461 [CQOI2018]九连环
思路:\(DP\) 提交:\(2\)次 错因:高精写挂(窝太菜了) 题解: 观察可知\(f[i]=2*f[i-1]+(n\&1)\) 高精的过程参考了WinXP@luogu的思路: 发现一个问 ...
- 008_linuxC++之_类的静态变量和静态函数
(一)看程序 #include <iostream> #include <string.h> #include <unistd.h> using namespace ...
- [Luogu] U18430 萌萌的大河
https://www.luogu.org/problemnew/show/U18430 思路比较好想 树链剖分 对于1操作 只需将以该点为根的子树打标记,将所有数存入数组排序 每次进行1操作时,判断 ...
- [POI] 大都市meg
http://www.lydsy.com/JudgeOnline/problem.php?id=1103 树剖边权转点权,vector存图卡一下午RE 气炸.. #include <iostre ...
- 【概率论】3-7:多变量分布(Multivariate Distributions Part I)
title: [概率论]3-7:多变量分布(Multivariate Distributions Part I) categories: Mathematic Probability keywords ...
- scrapy框架之Pipeline管道类
Item Pipeline简介 Item管道的主要责任是负责处理有蜘蛛从网页中抽取的Item,他的主要任务是清洗.验证和存储数据.当页面被蜘蛛解析后,将被发送到Item管道,并经过几个特定的次序处理数 ...
- CF1206A
CF1206A 题意: 给你 $ a , b $ 两个数组,要求从两个数组中各选一个数,使得它们的和不存在于任何一个数组. 解法: 一道极端签到的题. 因为是要构建一个不存于两个数组的数,所以直接将两 ...
- richtextbox Ctrl+V只粘贴纯文本格式
只能粘贴剪切板中的TXT内容 并且 不能改变 剪切板的内容1 当用户按下Ctrl+V屏蔽系统的粘贴功能,然后添加自己的功能2019年12月19日 19:34:38 private void richT ...
- pwn学习日记Day15 《程序员的自我修养》读书笔记
程序编译链接过程: 1.调用cc1程序,这个程序实际上就是GCC的C语言编译器,它将"hello.c"编译成一个临时的汇编文件"/tmp/ccUhtGSB.s" ...
- 官网引用的axios,lodash文件在脚手架中如何使用?
对于官网属性与侦听器模块,所引用的以下文件在脚手架中如何使用? <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/ ...