您的位置:首页 > 编程语言 > Go语言

poj-2195-Going Home(最小费用最大流模板题)

2016-05-21 19:30 465 查看
传送门

最小费用最大流模板

题意:

有n个人和n个房子,让每个人都回到一个房子里面,使得所有人走的步数和最小

建图:源点0,汇点:2*n+1,从源点到汇点建立一个容量为1,费用为0 的一条边,从每个房子到汇点建立一个容量为1,费用为0 的一条边;每个人到每个房子建立一条容量为1,费用为两者距离的边。图建好之后就可以直接求最小费用最大流了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define MAXN 1003
#define MAXM 40004
using namespace std;
const int INF = 0x3f3f3f3f;
struct EDGE{
int to, next, cap, flow, cost;
}edge[MAXM];
struct Point{
int x, y;
}men[MAXN], house[MAXN];
int q[MAXN*10], head[MAXN], tol, menNum, houseNum, n, m;
int pre[MAXN], dis[MAXN];
bool vis[MAXN];
char g[110];
void init(){
tol = 0;
menNum = 1;
houseNum = 1;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int cap, int cost){
edge[tol].to = v;
edge[tol].cap = cap;
edge[tol].cost = cost;
edge[tol].flow = 0;
edge[tol].next = head[u];
head[u] = tol++;
edge[tol].to = u;
edge[tol].cap = 0;
edge[tol].cost = -cost;
edge[tol].flow = 0;
edge[tol].next = head[v];
head[v] = tol++;
}
bool spfa(int st, int en){
int rear = 0, front = 0;
for (int i = 0; i <= en; i++){
dis[i] = INF;
vis[i] = false;
pre[i] = -1;
}
dis[st] = 0;
vis[st] = true;
q[front++] = st;
while(rear < front){
int u = q[rear++];
vis[u] = false;
for (int e = head[u]; e != -1; e = edge[e].next){
int v = edge[e].to;
if (edge[e].cap > edge[e].flow && dis[v] > dis[u]+edge[e].cost){
dis[v] = dis[u]+edge[e].cost;
pre[v] = e;
if (!vis[v]){
vis[v] = true;
q[front++] = v;
}
}
}
}
return pre[en] != -1;
}
int minCostMaxFlow(int st, int en, int &cost){
int flow = 0;
while(spfa(st, en)){
int Min = INF;
for (int i = pre[en]; i != -1; i = pre[edge[i^1].to]){
Min = (Min > (edge[i].cap-edge[i].flow) ? (edge[i].cap-edge[i].flow) : Min);
}
for (int i = pre[en]; i != -1; i = pre[edge[i^1].to]){
edge[i].flow += Min;
edge[i^1].flow -= Min;
cost += Min*edge[i].cost;
}
}
return flow;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.txt", "r", stdin);
#endif
int i, j, k, cost, u, v, st, en;
while(1) {
scanf("%d%d", &n, &m);
if (!n && !m){
break;
}
init();
for (i = 0; i < n; i++){
scanf("%s", g);
for (j = 0; j < m; j++){
if (g[j]=='H'){
men[menNum].x = i;
men[menNum].y = j;
menNum++;
}else if (g[j]=='m'){
house[houseNum].x = i;
house[houseNum].y = j;
houseNum++;
}
}
}
st = 0;
en = menNum+houseNum-1;
for (i = 1; i < menNum; i++){
for (j = 1; j < houseNum; j++){
addEdge(i, menNum+j-1, 1, abs(men[i].x-house[j].x)+abs(men[i].y-house[j].y));
}
}
cost = 0;
for (i = 1; i < menNum; i++) {
addEdge(0, i, 1, 0);
addEdge(i+menNum-1, en, 1, 0);
}
minCostMaxFlow(st, en, cost);
printf("%d\n", cost);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: