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; }
相关文章推荐
- Google官方详解 Activity【项目实例不容错过!】
- View初始 INVISIBLE GONE时,执行Animation动画效果
- good good study day day up
- Django 开发-管理站点管理应用数据
- Django form表单修改数据
- UVa 11292 Dragon of Loowater (水题,排序)
- Google自己的下拉刷新组件SwipeRefreshLayout
- Django笔记 解决找不到vcvarsall.bat的错误
- Codeforces 639B——Bear and Forgotten Tree 3——————【构造、树】
- 用Golang来AC
- Django入门之自定义页面
- golang C相互调用带参数
- 突破限制爬取网页数据 googlesholar为例【转】
- Django管理后台的搭建
- 为什么golang的for循环后的大括号必须跟在for关键字后面
- 【hdu3635】Dragon Balls —— 并查集
- google chrome 开发者工具选项(三)
- golang实现unicode码和中文之间的转换
- 【Django】本地csv数据的页面table展示
- Win7,8的上帝模式文件夹 GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}