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

POJ-2195 Going Home(最小费用最大流)

2016-06-01 08:09 399 查看
先记录每个人每个房子的坐标。以0为源点和每个人连一条容量为1,费用为零的的边,在从每个人出发和所有的房子都连上一条容量为1,费用为他们之间距离的边,最有从每个房子出发和汇点连一条容量为零,费用为零的边.

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#include <queue>
#define maxn 10005
#define INF 1000000000
using namespace std;
typedef long long ll;
struct Node{
Node(int a, int b){
x = a;
y = b;
}
int x, y;
};
struct Edge{
Edge(){
}
Edge(int a, int b, int c, int d, int e){
from = a;
to = b;
cap = c;
flow = d;
cost = e;
}
int from, to, cap, flow, cost;
};
vector<Edge> edge;
vector<int> v[maxn];
vector<Node> p1, p2;
int n, m;
int a[maxn], p[maxn], d[maxn], in[maxn];
char vis[maxn][maxn];
void Addedge(int from, int to, int cap, int flow, int cost){

edge.push_back(Edge(from, to, cap, 0, cost));
edge.push_back(Edge(to, from, 0, 0, -cost));
int dd = edge.size();
v[from].push_back(dd-2);
v[to].push_back(dd-1);

}
void Init(){

scanf("%d%d", &n, &m);
edge.clear();
for(int i = 0; i < maxn; i++)
v[i].clear();
p1.clear();
p2.clear();
for(int i = 0; i < n; i++){
scanf("%s", vis[i]);
for(int j = 0; vis[i][j]; j++){
if(vis[i][j] == 'H')
p2.push_back(Node(i, j));
else if(vis[i][j] == 'm')
p1.push_back(Node(i, j));
}
}
int k1 = p1.size(), k2 = p2.size();
for(int i = 0; i < k1; i++)
for(int j = 0; j < k2; j++){
Addedge(i+1, j+1+k1, 1, 0, abs(p1[i].x-p2[j].x)+abs(p1[i].y-p2[j].y));
}
for(int i = 0; i < k1; i++)
Addedge(0, i+1, 1, 0, 0);
for(int i = 0; i < k2; i++)
Addedge(k1+i+1, k1+k2+1, 1, 0, 0);
}
int SPFA(){

int ans = 0, e = p1.size() + p2.size() + 1;

while(1){
a[0] = INF;
for(int i = 1; i <= e; i++)
d[i] = INF;
d[0] = 0;
memset(in, 0, sizeof(in));
queue<int> q;
q.push(0);
while(!q.empty()){

int dd = q.front();
q.pop();
in[dd] = 0;
for(int j = 0; j < v[dd].size(); j++){

Edge &e = edge[v[dd][j]];
if(d[e.to] > d[dd] + e.cost && e.cap > e.flow){
d[e.to] = d[dd] + e.cost;
a[e.to] = min(a[dd], e.cap - e.flow);
p[e.to] = v[dd][j];
if(in[e.to] == 0){
q.push(e.to);
in[e.to] = 1;
}
}
}
}
if(d[e] == INF)
break;
ans += a[e] * d[e];
for(int i = e; i != 0; i = edge[p[i]].from){
edge[p[i]].flow += a[e];
edge[p[i]^1].flow -= a[e];
}
}
return ans;
}
int main(){

//  freopen("in.txt", "r", stdin);
while(scanf("%d%d", &n, &m) == 2){
if(n == 0 && m == 0)
break;
Init();
cout << SPFA() << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: