http://blog.csdn.net/qq564690377/article/details/17082055

做的时候觉得明显是费用流,但是真的不知道怎么建图,看了上面的博客会稍微清晰一点。后面再补一点细节吧,然后发现这道题用自己平时的费用流模板是水不过去的,所以找了份别人AC的代码弄了个zkw最小费用流的模板上来,算是存下模板吧。

补充点个人的理解吧,个人的网络流做的题还是太少了,所以想不到怎么建模,其实感觉上还是比较直接的一个行列二分图建模。首先就是枚举最后有多少个1剩下来,假设当前的已经有cur个1了,然后我要达到tot,那么每一行应该有tot/n个,每一列应该有tot/m个,所以我们可以对每行建一个点,对每列建一个点,从源点到行的点限流tot/n,列的点到汇点限流tot/m,这样的话当满流的时候其实就能保证每一行的1相等,每一列的1也相等。然后建边的时候就是每个处于(i,j)的点和i行j列的点连一条边,假设原本是1就费用为0,原本是0就费用为1.那么按照这样跑一遍费用流,费用x就是图里面需要由0变成1的点的个数,我们只需要再求出y,即图里由1变成0的个数就可以了。那么y等于多少呢? 不难发现图中多出来的1应该满足 x-y=tot-cur  所以y=x+cur-tot  所以最后的费用是x+y=2*x+cur-tot。

http://blog.sina.com.cn/s/blog_61034ad90100gwdw.html

上面的博客研究了spfa的网络流和zkw的网络流,可能zkw网络流会比较适用在二分图,稠密图上吧。

  1. #pragma warning(disable:4996)
  2. #include <iostream>
  3. #include <cstring>
  4. #include <string>
  5. #include <vector>
  6. #include <cmath>
  7. #include <algorithm>
  8. #include <cstdio>
  9. #include <queue>
  10. using namespace std;
  11.  
  12. #define ll long long
  13. #define eps 1e-8
  14. #define maxn 100
  15. #define maxe 4000
  16. #define inf 0x3f3f3f3f
  17. using namespace std;
  18.  
  19. char b[50][50];
  20. int n, m;
  21.  
  22. /*int siz;
  23.  
  24. struct Edge{
  25. int u, v, nxt, cap, cost;
  26. }edge[maxe];
  27. int head[maxn];
  28.  
  29. struct MinCostMaxFlow
  30. {
  31. queue<int> que;
  32. int add; // edges number
  33. int vn; // total vertex number
  34. int cost[maxn], in[maxn], pre[maxn];
  35. bool vis[maxn];
  36. void init(){
  37. add = 0; vn = siz + 10; memset(head, -1, sizeof(head));
  38. while (!que.empty()) que.pop();
  39. }
  40. void insert(int u, int v, int w, int c){
  41. edge[add].u = u; edge[add].v = v; edge[add].cap = w; edge[add].cost = c;
  42. edge[add].nxt = head[u]; head[u] = add++;
  43. edge[add].u = v; edge[add].v = u; edge[add].cap = 0; edge[add].cost = -c;
  44. edge[add].nxt = head[v]; head[v] = add++;
  45. }
  46.  
  47. bool spfa(int s, int e){
  48. memset(cost, 0x3f3f3f3f, sizeof(cost));
  49. memset(in, 0, sizeof(in));
  50. memset(vis, 0, sizeof(vis));
  51. cost[s] = 0; pre[s] = -1;
  52. que.push(s); vis[s] = true; in[s]++;
  53. while (!que.empty()){
  54. int u = que.front(); que.pop();
  55. vis[u] = false;
  56. for (int i = head[u]; i != -1; i = edge[i].nxt){
  57. int v = edge[i].v;
  58. if (edge[i].cap > 0 && cost[v] > cost[u] + edge[i].cost){
  59. cost[v] = cost[u] + edge[i].cost; pre[v] = i;
  60. if (!vis[v]){
  61. que.push(v); vis[v] = true; in[v]++;
  62. if (in[v] > vn) return false;
  63. }
  64. }
  65. }
  66. }
  67. if (cost[e] < inf) return true;
  68. else return false;
  69. }
  70. int mincostmaxflow(int s, int e){
  71. int mincost = 0, maxflow = 0;
  72. while (spfa(s, e)){
  73. int flow = inf;
  74. for (int i = pre[e]; i != -1; i = pre[edge[i].u]){
  75. flow = min(flow, edge[i].cap);
  76. }
  77. maxflow += flow;
  78. for (int i = pre[e]; i != -1; i = pre[edge[i].u]){
  79. edge[i].cap -= flow;
  80. edge[i ^ 1].cap += flow;
  81. }
  82. mincost += cost[e] * flow;
  83. }
  84. return mincost;
  85. }
  86. }net;
  87. */
  88.  
  89. struct Edge
  90. {
  91. int u, v, cap, cost, nxt;
  92. Edge(int _u, int _v, int _cap, int _cost, int _nxt) :
  93. u(_u), v(_v), cap(_cap), cost(_cost), nxt(_nxt){}
  94. Edge(){};
  95. }edge[maxe];
  96. int head[maxn];
  97.  
  98. struct ZKW_MinCostMaxFlow {
  99. int add;
  100. int cur[maxn];
  101. int dis[maxn];
  102. bool inq[maxn];
  103. queue<int> q;
  104. bool vis[maxn];
  105.  
  106. int ss, tt, n;
  107. int min_cost, max_flow;
  108.  
  109. void init() {
  110. memset(head, -1, sizeof(head));
  111. add = 0;
  112. }
  113.  
  114. void insert(int u, int v, int cp, int ct) {
  115. edge[add] = Edge(u, v, cp, ct, head[u]);
  116. head[u] = add++;
  117. edge[add] = Edge(v, u, 0, -ct, head[v]);
  118. head[v] = add++;
  119. }
  120.  
  121. int aug(int u, int flow) {
  122. if (u == tt) return flow;
  123. vis[u] = true;
  124. for (int i = cur[u]; i != -1; i = edge[i].nxt) {
  125. int v = edge[i].v;
  126. if (edge[i].cap && !vis[v] && dis[u] == dis[v] + edge[i].cost) {
  127. int tmp = aug(v, min(flow, edge[i].cap));
  128. edge[i].cap -= tmp;
  129. edge[i ^ 1].cap += tmp;
  130. cur[u] = i;
  131. if (tmp) return tmp;
  132. }
  133. }
  134. return 0;
  135. }
  136. bool modify_label() {
  137. int d = inf;
  138. for (int u = 0; u < n; u++) if (vis[u])
  139. for (int i = head[u]; i != -1; i = edge[i].nxt) {
  140. int v = edge[i].v;
  141. if (edge[i].cap && !vis[v])
  142. d = min(d, dis[v] + edge[i].cost - dis[u]);
  143. }
  144. if (d == inf) return false;
  145. for (int i = 0; i < n; ++i) if (vis[i]) {
  146. vis[i] = false;
  147. dis[i] += d;
  148. }
  149. return true;
  150. }
  151.  
  152. pair<int, int> mincostmaxflow(int s, int t, int _n) {
  153. ss = s, tt = t, n = _n;
  154. min_cost = max_flow = 0;
  155. for (int i = 0; i < n; i++) dis[i] = 0;
  156. while (true) {
  157. for (int i = 0; i < n; i++) cur[i] = head[i];
  158. while (true) {
  159. for (int i = 0; i < n; i++) vis[i] = 0;
  160. int tmp = aug(s, inf);
  161. if (tmp == 0) break;
  162. max_flow += tmp;
  163. min_cost += tmp * dis[ss];
  164. }
  165. if (!modify_label()) break;
  166. }
  167. return make_pair(min_cost, max_flow);
  168. }
  169. }net;
  170.  
  171. int main()
  172. {
  173. int T; cin >> T; int ca = 0;
  174. while (T--){
  175. scanf("%d%d", &n, &m);
  176. for (int i = 0; i < n; i++) scanf("%s", b[i]);
  177. int tot = 0;
  178. for (int i = 0; i < n; ++i){
  179. for (int j = 0; j < m; ++j){
  180. if (b[i][j] == '1') tot++;
  181. }
  182. }
  183. int ans = min(n*m - tot, tot);
  184. for (int i = 1; i <= n*m; ++i){
  185. if (i%n != 0 || i%m != 0) continue;
  186. if (abs(tot - i) >= ans) continue;
  187. net.init();
  188. int src = n + m, sink = src + 1;
  189. for (int k = 0; k < n; ++k){
  190. net.insert(src, k, i / n, 0);
  191. }
  192. for (int k = n; k < n + m; k++){
  193. net.insert(k, sink, i / m, 0);
  194. }
  195. for (int x = 0; x < n; x++){
  196. for (int j = 0; j < m; j++){
  197. if (b[x][j] == '1') net.insert(x, j + n, 1, 0);
  198. else net.insert(x, j + n, 1, 1);
  199. }
  200. }
  201. ans = min(ans, net.mincostmaxflow(src, sink,sink+1).first * 2 + tot - i);
  202. }
  203. printf("Case %d: %d\n", ++ca, ans);
  204. }
  205. return 0;
  206. }

uva12534 Binary Matrix 2(最小费用最大流)的更多相关文章

  1. [poj] 3422 Kaka's Matrix Travels || 最小费用最大流

    原题 给一个N*N的方阵,从[1,1]到[n,n]走K次,走过每个方格加上上面的数,然后这个格上面的数变为0.求可取得的最大的值. 要求最大值,所以把边权全为负跑最小费用即可.因为只有第一次经过该点的 ...

  2. UVa11082 Matrix Decompressing(最小费用最大流)

    题目大概有一个n*m的矩阵,已知各行所有数的和的前缀和和各列所有数的和的前缀和,且矩阵各个数都在1到20的范围内,求该矩阵的一个可能的情况. POJ2396的弱化版本吧..建图的关键在于: 把行.列看 ...

  3. hdu 2686 Matrix 最小费用最大流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 Yifenfei very like play a number game in the n*n ...

  4. POJ 3422 Kaka&#39;s Matrix Travels (最小费用最大流)

    POJ 3422 Kaka's Matrix Travels 链接:http://poj.org/problem? id=3422 题意:有一个N*N的方格,每一个方格里面有一个数字.如今卡卡要从左上 ...

  5. POJ 3422 Kaka's Matrix Travels 【最小费用最大流】

    题意: 卡卡有一个矩阵,从左上角走到右下角,卡卡每次只能向右或者向下.矩阵里边都是不超过1000的正整数,卡卡走过的元素会变成0,问卡卡可以走k次,问卡卡最多能积累多少和. 思路: 最小费用最大流的题 ...

  6. poj3422 Kaka's Matrix Travels(最小费用最大流问题)

    /* poj3422 Kaka's Matrix Travels 不知道 k次 dp做为什么不对??? 看了大牛的代码,才知道还可以这样做! 开始没有理解将a 和 a‘ 之间建立怎样的两条边,导致程序 ...

  7. hdu 2686 Matrix && hdu 3367 Matrix Again (最大费用最大流)

    Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  8. HDU3376 最小费用最大流 模板2

    Matrix Again Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)To ...

  9. hdu 3395(KM算法||最小费用最大流(第二种超级巧妙))

    Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

随机推荐

  1. Sublime Text 2编译python时出错

    [Error 2] The system cannot find the file specified [Finished]   解决方法: 1.环境变量path添加: C:\Python32\Too ...

  2. python的http请求应用--每日签到

    写点python吧,python其实是个很好用的工具,作为浇水语言,跟其他语言联系也很紧密,想用什么包直接import,导入ctypes调用底层函数库,导入web相关的包可以轻松写爬虫,今天我们写的跟 ...

  3. ASP.NET浏览器定义文件及IE兼容模式

    由于ASP.NET4.0中的一个小bug,导致了ASP.NET WebForms控制的CallBack无效,部分控件无法使用. 解决方法是在项目中添加自定义的浏览器定义文件,参考这里:http://w ...

  4. ios中怎么样自动剪切图片周围超出的部分

    UIImageView *image = [[UIImageView alloc] init]; image.clipsToBounds = YES;

  5. 使用Git和远程代码库

    git是个了不起但却复杂的源代码管理系统.它能支持复杂的任务,却因此经常被认为太过复杂而不适用于简单的日常工作.让我们诚实一记吧:Git是复杂的,我们不要装作它不是.但我仍然会试图教会你用(我的)基本 ...

  6. Android HttpClient GET或者POST请求基本使用方法(转)

    在Android开发中我们经常会用到网络连接功能与服务器进行数据的交互,为此Android的SDK提供了Apache的HttpClient来方便我们使用各种Http服务.这里只介绍如何使用HttpCl ...

  7. [转]ubuntu 14.04 系统设置不见了

    [转]ubuntu 14.04 系统设置不见了 http://blog.sina.com.cn/s/blog_6c9d65a10101i0i7.html 不知道删除什么了,系统设置不见了! 我在终端运 ...

  8. 权重轮询调度算法(Weighted Round-Robin Scheduling)-C#实现

    在多台机器实现负载均衡的时候,存在调度分配的问题. 如果服务器的配置的处理能力都一致的话,平均轮询分配可以直接解决问题,然而有些时候机器的处理能力是不一致的. 假如有2台机器 A和B , A的处理能力 ...

  9. SQL SERVER发布与订阅 [原创]

    一.配置分发 1.配置分发服务器,注:配置发布与订阅,连接SQLSERVER必须用服务器名登录 2.配置分发 3.选择分发服务器 4.选择快照文件夹 5.设置此文件夹的读写权限为everyone 6. ...

  10. 浅谈ERP系统实施后如何完善企业内部控制制度建设

    ERP与企业内部控制制度,前者提升企业的管理水平,后者为企业发展保驾护航,两项工作都是企业各项工作的重中之重. ERP是企业资源规划Enterprise Resource Planning的缩写.企业 ...