poj 2195 Going Home【zkw费用流】
来源:互联网 发布:无用神力兄弟会 知乎 编辑:程序博客网 时间:2024/06/10 01:33
题目链接:http://poj.org/problem?id=2195
题意:每个人都走到一个屋子的最小花费。二分图类型
代码:
#include <iostream> #include <algorithm> #include <set> #include <map> #include <string.h> #include <queue> #include <sstream> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string>using namespace std;const int MAXN = 1000;const int MAXM = 200000;const int INF = 0x3f3f3f3f;struct Edge{ int to, next, cap, flow, cost; Edge(int _to = 0, int _next = 0, int _cap = 0, int _flow = 0, int _cost = 0) : to(_to), next(_next), cap(_cap), flow(_flow), cost(_cost) {}}edge[MAXM];struct ZKW_MinCostMaxFlow{ int head[MAXN], tot; int cur[MAXN]; int dis[MAXN]; bool vis[MAXN]; int ss, tt, N;//源点、汇点和点的总个数(编号是0~N-1),不需要额外赋值,调用会直接赋值 int min_cost, max_flow; void init() { tot = 0; memset(head, -1, sizeof(head)); } void addedge(int u, int v, int cap, int cost) { edge[tot] = Edge(v, head[u], cap, 0, cost); head[u] = tot++; edge[tot] = Edge(u, head[v], 0, 0, -cost); head[v] = tot++; } int aug(int u, int flow) { if (u == tt)return flow; vis[u] = true; for (int i = cur[u];i != -1;i = edge[i].next) { int v = edge[i].to; if (edge[i].cap > edge[i].flow && !vis[v] && dis[u] == dis[v] + edge[i].cost) { int tmp = aug(v, min(flow, edge[i].cap - edge[i].flow)); edge[i].flow += tmp; edge[i ^ 1].flow -= tmp; cur[u] = i; if (tmp)return tmp; } } return 0; } bool modify_label() { int d = INF; for (int u = 0;u < N;u++) if (vis[u]) for (int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].to; if (edge[i].cap>edge[i].flow && !vis[v]) d = min(d, dis[v] + edge[i].cost - dis[u]); } if (d == INF)return false; for (int i = 0;i < N;i++) if (vis[i]) { vis[i] = false; dis[i] += d; } return true; } /* * 直接调用获取最小费用和最大流 * 输入: start-源点,end-汇点,n-点的总个数(编号从0开始) * 返回值: pair<int,int> 第一个是最小费用,第二个是最大流 */ pair<int, int> mincostmaxflow(int start, int end, int n) { ss = start, tt = end, N = n; min_cost = max_flow = 0; for (int i = 0;i < n;i++)dis[i] = 0; while (1) { for (int i = 0;i < n;i++)cur[i] = head[i]; while (1) { for (int i = 0;i < n;i++)vis[i] = false; int tmp = aug(ss, INF); if (tmp == 0)break; max_flow += tmp; min_cost += tmp*dis[ss]; } if (!modify_label())break; } return make_pair(min_cost, max_flow); }}solve;int n, m;char s[110][110];int main(){ while (~scanf("%d%d", &n, &m)) { if (n == 0 && m == 0) break; solve.init(); for (int i = 0;i < n;i++) { scanf("%s", s[i]); for (int j = 0;j < m;j++) if (s[i][j] == 'H') solve.addedge(n*m, i*m + j, 1, 0); else if (s[i][j] == 'm') solve.addedge(i*m + j, n*m + 1, 1, 0); } for (int i = 0;i < n*m;i++) for (int j = 0;j < n*m;j++) { int x1 = i / m; int y1 = i % m; int x2 = j / m; int y2 = j % m; if (s[x1][y1] == 'H' && s[x2][y2] == 'm') solve.addedge(i, j, 1, abs(x1 - x2) + abs(y1 - y2)); } pair<int, int> ans = solve.mincostmaxflow(n * m, n * m + 1, n*m + 2); printf("%d\n",ans.first); } return 0;}
0 0
- poj 2195 Going Home【zkw费用流】
- hdu 1533 Going Home(zkw费用流)
- POJ 2195 Going Home(费用流)
- poj 2195 Going Home (费用流)
- [费用流] POJ 2195 Going Home
- poj 2195 Going Home (费用流/KM)
- POJ 2195 Going Home(费用流)
- [POJ 2195]Going Home[费用流]
- Poj 2195 Going Home【费用流Min_Cost_Max_flow】
- POJ 2195 Going Home <最小费用流>
- Poj 2195 Going Home(费用流)
- POJ 2195 Going Home (费用流)
- POJ 2195 Going Home 最小费用流
- POJ 2195 Going Home(网络流-费用流)
- POJ 2195 Going Home (网络流之最小费用流)
- poj-2195-Going Home最小费用最大流
- poj - 2195 - Going Home(最小费用最大流)
- poj 2195 Going Home(KM||费用流)
- 自学QT之实现一个用户信息窗口
- js window.open 打开页面并居中
- 文法相关
- Circle vs Triangle(DFS+博弈)
- java练习:金额转换,阿拉伯数字转换成中文传统形式
- poj 2195 Going Home【zkw费用流】
- HDU 2222 Keywords Search(AC自动机)
- Linux中Tomcat 自动设置CATALINA_HOME方法
- scala (6)柯里化
- 自旋锁在内核中的实现
- 'sessionFactory' or 'hibernateTemplate' is required
- 2.1.4 Shading in World Space (about uniforms) 在世界坐标系里着色(关于uniforms参数)
- 在c#中使用sqlite的两个注意点
- [BZOJ1878][SDOI2009]HH的项链