kuangbin专题专题十一 网络流 Going Home POJ - 2195
2024-09-06 09:50:17
题目链接:https://vjudge.net/problem/POJ-2195
思路:曼哈顿距离来求每个人到每个房间的距离,把距离当作费用。
就可以用最小费用最大流来解决了,把每个房子拆成两个点,限流。
源点->人->房入->房出->汇点。流量的话都设置为1,起到限流作用。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
using namespace std; const int N = ,INF = (int)1e9;
int n,m,tot,num;
int head[N<<],d[N<<],vis[N<<],pre[N<<];
char mp[N][N];
vector<pair<int,int > > p;
vector<pair<int,int > > h;
struct node{
int to,nxt,cap,flow,cost;
}e[N*N]; void show(){
cout << endl;
for(int i = ; i < n; ++i) cout << mp[i] << endl;
for(int i = ; i < num; ++i) printf("( %d, %d) ",p[i].first,p[i].second);
cout << endl;
for(int i = ; i < num; ++i) printf("( %d, %d) ",h[i].first,h[i].second);
cout << endl << endl;
}
//求距离
inline int _dis(int x,int y){
return abs(p[x].first - h[y].first) + abs(p[x].second - h[y].second);
} inline void add(int u,int v,int cap,int flow,int cost){
e[tot].to = v;
e[tot].cap = cap;
e[tot].flow = flow;
e[tot].cost = cost;
e[tot].nxt = head[u];
head[u] = tot++;
e[tot].to = u;
e[tot].cap = ;
e[tot].flow = flow;
e[tot].cost = -cost;
e[tot].nxt = head[v];
head[v] = tot++;
} void build_map(int s,int t){ //0源点 1~num人 num+1~2*num 房入 2*num+1~3*num房出 3*num+1汇点
int cost;
for(int i = ; i < num; ++i){
for(int j = ; j < num; ++j){
cost = _dis(i,j);
add(i+,j++num,,,cost);
}
}
for(int i = ; i < num; ++i) add(s,i+,,,);
for(int i = ; i < num; ++i) add(i++num,i++*num,,,);
for(int i = ; i < num; ++i) add(i++*num,t,,,);
} bool spfa(int s,int t){
for(int i = s; i <= t; ++i) pre[i] = -;
for(int i = s; i <= t; ++i) d[i] = INF; d[s] = ;
for(int i = s; i <= t; ++i) vis[i] = false; vis[s] = true;
queue<int > que;
que.push(s);
while(!que.empty()){
int now = que.front(); que.pop();
vis[now] = false;
for(int o = head[now]; ~o; o = e[o].nxt){
int to = e[o].to;
if(e[o].cap > e[o].flow && d[to] > d[now] + e[o].cost){
d[to] = d[now] + e[o].cost;
pre[to] = o;
if(!vis[to])
vis[to] = true;
que.push(to);
}
}
}
if(pre[t] == -) return false;
else return true;
} int work(){ int s = ,t = *num+,ans = ;
for(int i = s; i <= t; ++i) head[i] = -; tot = ;
build_map(s,t);
while(spfa(s,t)){
int Min = INF;
for(int o = pre[t]; ~o; o = pre[e[o^].to]){
Min = min(Min,e[o].cap - e[o].flow);
}
for(int o = pre[t]; ~o; o = pre[e[o^].to]){
e[o].flow += Min;
e[o^].flow -= Min;
}
ans += Min*d[t];
}
return ans;
} int main(){ while(~scanf("%d%d",&n,&m) && (n+m)){
for(int i = ; i < n; ++i) scanf("%s",mp[i]);
p.clear(); h.clear();
for(int i = ; i < n; ++i){
for(int j = ; j < m; ++j){
if(mp[i][j] == 'm') p.push_back(make_pair(i,j));
if(mp[i][j] == 'H') h.push_back(make_pair(i,j));
}
}
num = p.size();
//show();
//cout << "------------------------------------" << work() << endl;
cout << work() << endl;
} return ;
}
最新文章
- bzoj 3718
- Android开发学习清单
- x01.os.9: 进程切换
- C# Reflection Type/MethodInfo
- CLH锁 、MCS锁
- How to create a PPPoE Server on Ubuntu? (Untested)
- C#中实现邮件发送功能
- 时刻注意QT与Windows系统的不同(惨痛教训)
- C# XML与Json之间相互转换
- POJ3313 【随便写了个spfa就一A了,嗨皮】
- TMS320F28335项目开发记录5_28335之CCS编程基础
- JSP技术模型(五)JSP隐含变量
- spring的@Transactional注解详细用法
- Windows系统顽固文件删除方法
- appium+python做移动端自动化测试
- 命令行保存指定目录文件的名字(可包含文件夹文字)到txt文本文件
- 打造MacOS版“XShell”
- Ansible快速上手
- h5或者微信端吊起app
- C# Note17: 使用Ionic.Zip.dll实现解压缩文件