HDU1533 最小费用最大流
Going Home
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6478 Accepted Submission(s): 3411
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.
题意 n个人 n个房子 在N*M个方格 人移动一格要花费 1(只能水平竖直四个方向) 问n个人走到n个房子的最小花费是多少(一个房子只能一个人待)
解析 这道题可以转化成费用流来解决,n个源点n个汇点 最大流为n的最小费用 ,我们直接建立一个超源点0,一个超汇点n*m+1 然后和源点汇点相连 容量1 费用0
注意 其他边的费用为1 但是容量要设为inf 因为走过之后还可以走.
也可以用二分图最大全匹配写 还没get这项技能。。。
代码一 // 一比二快100ms。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+,mod=1e9+,inf=0x3f3f3f3f;
typedef long long ll;
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n");
#define debug(a,b) cout<<a<<" "<<b<<" ";
int dir[][]={{,},{-,},{,-},{,}};
char a[maxn][maxn];
struct MCMF {
struct Edge {
int from, to, cap, cost;
Edge(int u, int v, int w, int c): from(u), to(v), cap(w), cost(c) {}
};
int n, s, t;
vector<Edge> edges;
vector<int> G[maxn];
int inq[maxn], d[maxn], p[maxn], a[maxn]; void init(int n) {
this->n = n;
for (int i = ; i <= n; i ++) G[i].clear();
edges.clear();
}
void addedge(int from, int to, int cap, int cost) {
edges.push_back(Edge(from, to, cap, cost));
edges.push_back(Edge(to, from, , -cost));
int m = edges.size();
G[from].push_back(m - );
G[to].push_back(m - );
}
bool BellmanFord(int s, int t, int &flow, int &cost) {
for (int i = ; i <= n; i ++) d[i] = inf;
memset(inq, , sizeof(inq));
d[s] = ; inq[s] = ; p[s] = ; a[s] = inf; queue<int> Q;
Q.push(s);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = ;
for (int i = ; i < G[u].size(); i ++) {
Edge &e = edges[G[u][i]];
if (e.cap && d[e.to] > d[u] + e.cost) {
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u], e.cap);
if (!inq[e.to]) {
Q.push(e.to);
inq[e.to] = ;
}
}
}
}
if (d[t] == inf) return false;
flow += a[t];
cost += d[t] * a[t];
int u = t;
while (u != s) {
edges[p[u]].cap -= a[t];
edges[p[u] ^ ].cap += a[t];
u = edges[p[u]].from;
}
return true;
}
int solve(int s, int t) {
int flow = , cost = ;
while (BellmanFord(s, t, flow, cost));
return cost;
}
}solver;;
void build(int n,int m)
{
vector<int> ss,tt;
for(int i=;i<=n;i++)
{
scanf("%s",a[i]+);
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
int temp=(i-)*m+j;
if(a[i][j]=='m')
ss.push_back(temp);
else if(a[i][j]=='H')
tt.push_back(temp);
for(int k=;k<;k++)
{
int x=i+dir[k][];
int y=j+dir[k][];
if(x>=&&x<=n&&y>=&&y<=m)
{
int temp2=(x-)*m+y;
solver.addedge(temp,temp2,inf,);
// cout<<i<<" "<<j<<" "<<temp<<" "<<temp2<<endl;
}
}
}
}
for(int i=;i<ss.size();i++)
solver.addedge(,ss[i],,);
for(int i=;i<tt.size();i++)
solver.addedge(tt[i],n*m+,,);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)&&n&&m)
{
solver.init(n*m+);
build(n,m);
int maxflow;
maxflow=solver.solve(,n*m+);
printf("%d\n",maxflow);
}
}
代码二
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<queue>
using namespace std;
const int maxn=2e4+,mod=1e9+,inf=0x3f3f3f3f;
struct edge
{
int to,next,cap,flow,cost;
} edge[maxn*];
int head[maxn],tol;
int pre[maxn],dis[maxn];
bool vis[maxn];
int N;
char a[maxn][maxn];
void init(int n)
{
N=n,tol=;
memset(head,-,sizeof(head));
}
void addedge(int u,int v,int cap,int cost)
{
edge[tol].to=v;
edge[tol].cap=cap;
edge[tol].flow=;
edge[tol].cost=cost;
edge[tol].next=head[u];
head[u]=tol++;
edge[tol].to=u;
edge[tol].cap=;
edge[tol].flow=;
edge[tol].cost=-cost;
edge[tol].next=head[v];
head[v]=tol++;
}
bool spfa(int s,int t)
{
queue<int> q;
for(int i=; i<=N; i++)
{
dis[i]=inf;
vis[i]=false;
pre[i]=-;
}
dis[s]=;
vis[s]=true;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost)
{
dis[v]=dis[u]+edge[i].cost;
pre[v]=i;
if(!vis[v])
{
vis[v]=true;
q.push(v);
}
}
}
}
if(pre[t]==-) return false;
else return true;
}
int mincostflow(int s,int t,int &cost)
{
int flow=;
cost=;
while(spfa(s,t))
{
int Min=inf;
for(int i=pre[t]; i!=-; i=pre[edge[i^].to])
{
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
}
for(int i=pre[t]; i!=-; i=pre[edge[i^].to])
{
edge[i].flow+=Min;
edge[i^].flow-=Min;
cost+=edge[i].cost*Min;
}
flow+=Min;
}
return flow;
}
int dir[][]={{,},{-,},{,-},{,}};
void build(int n,int m)
{
vector<int> ss,tt;
for(int i=;i<=n;i++)
{
scanf("%s",a[i]+);
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
int temp=(i-)*m+j;
if(a[i][j]=='m')
ss.push_back(temp);
else if(a[i][j]=='H')
tt.push_back(temp);
for(int k=;k<;k++)
{
int x=i+dir[k][];
int y=j+dir[k][];
if(x>=&&x<=n&&y>=&&y<=m)
{
int temp2=(x-)*m+y;
addedge(temp,temp2,inf,);
// cout<<i<<" "<<j<<" "<<temp<<" "<<temp2<<endl;
}
}
}
}
for(int i=;i<ss.size();i++)
addedge(,ss[i],,);
for(int i=;i<tt.size();i++)
addedge(tt[i],n*m+,,);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)&&n&&m)
{
init(n*m+);
build(n,m);
int ans,maxflow;
maxflow=mincostflow(,n*m+,ans);
printf("%d\n",ans);
}
}
HDU1533 最小费用最大流的更多相关文章
- hdu1533 Going Home 最小费用最大流 构造源点和汇点
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- [hdu1533]二分图最大权匹配 || 最小费用最大流
题意:给一个n*m的地图,'m'表示人,'H'表示房子,求所有人都回到房子所走的距离之和的最小值(距离为曼哈顿距离). 思路:比较明显的二分图最大权匹配模型,将每个人向房子连一条边,边权为曼哈顿距离的 ...
- [板子]最小费用最大流(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 每个城市有一个犯罪团伙, 每个逮捕队伍在每个城市可以选 ...
随机推荐
- 阻止JEB 1.5频繁弹窗的办法
偶尔才用一次的JEB, 出现 “Controller没有响应或者无法访问, JEB即将终止.” 也懒得去逆了.直接用ProcessHacker找到对应的线程挂起即可.当然这只是临时的办法..我也只是临 ...
- SPI总线小结
串行外设接口(Serial Peripheral Interface,SPI)的缩写.是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线.Motorola首先在其MC68HCXX系列 ...
- UVA 11971 Polygon 多边形(连续概率)
题意: 一根长度为n的木条,随机选k个位置将其切成k+1段,问这k+1段能组成k+1条边的多边形的概率? 思路: 数学题.要求的是概率,明显与n无关. 将木条围成一个圆后再开切k+1刀,得到k+1段. ...
- smile domain name www.bn-nd.com for sell. Please contact boyanzheng at foxmail.com 微笑的域名。请联系邮箱。
- 【Conclusion】MySQL的安装和使用
MySQL使用 因为数据库实验用到了MySQL,这里对现在已经涉及到的MySQL部分操作做一个简单的小结. 1.安装MySQL 上MySQL的官网下载对应自己OS平台的MySQL安装文件,有在线安装和 ...
- 使用正则进行HTML页面属性的替换
使用正则表达式拼接富文本框 package com.goboosoft.common.utils; import org.apache.commons.lang3.StringUtils; impor ...
- 【转】Delphi 文件读写
procedure TForm1.Button1Click(Sender: TObject); variFileHandle: Integer;iFileLength: Integer;iBytesR ...
- 手把手入门docker (好多图)
1.什么是docker? ---->我的理解是将许多应用一起打包成一个镜像,拿这个镜像去其他服务器上运行起来就可以.不需要单个单个去配置啦. 2.怎样在window下的安装. ---->刚 ...
- 2019西安多校联训 Day5
T1 光哥为了不让某初二奆佬恶心到我们而留下的火种 (貌似没这题平均分就100-了) 思路:就一横一竖让后就gztopa嘛 #include <bits/stdc++.h> using n ...
- NOIP考纲
首先来一张图,很直观(截止到2012年数据) 下面是收集的一些,我改了一下 红色加粗表示特别重要,必须掌握绿色加粗表示最好掌握,可能性不是很大,但是某些可以提高程序效率 高精度 a.加法 b.减法 c ...