Description

有一个M * N的棋盘,有的格子是障碍。现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵。我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵。现在你的任务是要求使用最少个数的士兵来占领整个棋盘。

Input

第一行两个数M, N, K分别表示棋盘的行数,列数以及障碍的个数。 第二行有M个数表示Li。 第三行有N个数表示Ci。 接下来有K行,每行两个数X, Y表示(X, Y)这个格子是障碍。

Output

输出一个数表示最少需要使用的士兵个数。如果无论放置多少个士兵都没有办法占领整个棋盘,输出”JIONG!” (不含引号)

Sample Input

4 4 4
1 1 1 1
0 1 0 3
1 4
2 2
3 3
4 3

Sample Output

4
数据范围
M, N <= 100, 0 <= K <= M * N

Solution

有源汇上下界最小流……按行和列建二分图,分别向源汇点建立上下界为$[L_i,INF]$和$[C_i,INF]$的边,然后没有障碍点的两两连$[0,1]$的边,跑一遍就完了。

一个上下界网络流讲的很好的博客。注意别忘了$s$和$t$也要与$ss$和$tt$连边!

Code

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<queue>
  5. #define N (20009)
  6. #define INF (0x7f7f7f7f)
  7. using namespace std;
  8.  
  9. struct Edge{int to,next,flow;}edge[N*];
  10. int n,m,k,vis[][];
  11. int s=,t=,ss=,tt=;
  12. int Depth[N],A[N];
  13. int head[N],num_edge;
  14. queue<int>q;
  15.  
  16. inline int read()
  17. {
  18. int x=,w=; char c=getchar();
  19. while (!isdigit(c)) {if (c=='-') w=-; c=getchar();}
  20. while (isdigit(c)) x=x*+c-'', c=getchar();
  21. return x*w;
  22. }
  23.  
  24. void add(int u,int v,int l)
  25. {
  26. edge[++num_edge].to=v;
  27. edge[num_edge].next=head[u];
  28. edge[num_edge].flow=l;
  29. head[u]=num_edge;
  30. }
  31.  
  32. void Add(int u,int v,int l,int r)
  33. {
  34. add(u,v,r-l); add(v,u,);
  35. A[u]-=l; A[v]+=l;
  36. }
  37.  
  38. int DFS(int x,int low,int t)
  39. {
  40. if (x==t || !low) return low;
  41. int f=;
  42. for (int i=head[x]; i; i=edge[i].next)
  43. if (Depth[edge[i].to]==Depth[x]+)
  44. {
  45. int Min=DFS(edge[i].to,min(low,edge[i].flow),t);
  46. edge[i].flow-=Min;
  47. edge[((i-)^)+].flow+=Min;
  48. f+=Min; low-=Min;
  49. if (!low) break;
  50. }
  51. if (!f) Depth[x]=-;
  52. return f;
  53. }
  54.  
  55. bool BFS(int s,int t)
  56. {
  57. memset(Depth,,sizeof(Depth));
  58. Depth[s]=; q.push(s);
  59. while (!q.empty())
  60. {
  61. int x=q.front(); q.pop();
  62. for (int i=head[x]; i; i=edge[i].next)
  63. if (!Depth[edge[i].to] && edge[i].flow)
  64. {
  65. Depth[edge[i].to]=Depth[x]+;
  66. q.push(edge[i].to);
  67. }
  68. }
  69. return Depth[t];
  70. }
  71.  
  72. int Dinic(int s,int t)
  73. {
  74. int ans=;
  75. while (BFS(s,t)) ans+=DFS(s,INF,t);
  76. return ans;
  77. }
  78.  
  79. int main()
  80. {
  81. n=read(); m=read(); k=read(); s=n+m+; t=s+;
  82. for (int i=; i<=n; ++i) Add(s,i,read(),INF);
  83. for (int i=; i<=m; ++i) Add(i+n,t,read(),INF);
  84. for (int i=; i<=k; ++i) vis[read()][read()]=;
  85. for (int i=; i<=n; ++i)
  86. for (int j=; j<=m; ++j)
  87. if (!vis[i][j]) Add(i,j+n,,);
  88. int sum=;
  89. for (int i=; i<=n+m+; ++i)
  90. if (A[i]>) sum+=A[i], add(ss,i,A[i]), add(i,ss,);
  91. else add(i,tt,-A[i]), add(tt,i,);
  92. add(t,s,INF); add(s,t,);
  93. if (Dinic(ss,tt)!=sum) {puts("JIONG!"); return ;}
  94. for (int i=head[ss]; i; i=edge[i].next) edge[i].flow=edge[((i-)^)+].flow=;
  95. for (int i=head[tt]; i; i=edge[i].next) edge[i].flow=edge[((i-)^)+].flow=;
  96. int flow0=edge[num_edge].flow;
  97. edge[num_edge].flow=edge[num_edge-].flow=;
  98. printf("%d\n",flow0-Dinic(t,s));
  99. }

BZOJ1458:士兵占领(有上下界最小流)的更多相关文章

  1. 【bzoj1458】士兵占领 有上下界最小流

    题目描述 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵 ...

  2. BZOJ 1458 / Luogu P4311 士兵占领 (上下界最小流 / 直接最大流)

    做法1:上下界最小流 先来一发上下界最小流,思路比较暴力,就是把行和列看作n+mn+mn+m个点,(i,j)(i,j)(i,j)如果能占领就从第iii行向第jjj列连一条边,上界为1下界为0;然后从s ...

  3. 【BZOJ】1458: 士兵占领(上下界网络流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1458 是不是我脑洞太小了.......直接弄上下界最小流........(就当复习了.. 二分图X和 ...

  4. 【bzoj2150】部落战争 有上下界最小流

    题目描述 lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把 ...

  5. sgu 176 Flow construction(有源汇的上下界最小流)

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11025 [模型] 有源汇点的上下界最小流.即既满足上下界又满足 ...

  6. BZOJ_2502_清理雪道_有源汇上下界最小流

    BZOJ_2502_清理雪道_有源汇上下界最小流 Description        滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道), ...

  7. 【Loj117】有源汇上下界最小流(网络流)

    [Loj117]有源汇上下界最小流(网络流) 题面 Loj 题解 还是模板题. #include<iostream> #include<cstdio> #include< ...

  8. SGU 176 Flow construction (有源有汇有上下界最小流)

    题意:给定 n 个点,m 条有向边,如果有向边的标号是1的话,就表示该边的上界下界都为容量 ,如果有向边的标号为0的哈,表示该边的下界为0,上界为容量 ,现在问,从 1 到 n 的最小流是多少,并输出 ...

  9. loj #117. 有源汇有上下界最小流

    题目链接 有源汇有上下界最小流,->上下界网络流 注意细节,边数组也要算上后加到SS,TT边. #include<cstdio> #include<algorithm> ...

随机推荐

  1. [日常] Go语言圣经-Deferred函数

    1.只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法.当defer语句被执行时,跟在defer后面的函数会被延迟执行.直到包含该defer语句的函数执行完毕时,defe ...

  2. Java 内部类、静态内部类、匿名内部类

    java提高篇(八)----详解内部类 概念 可以将一个类的定义放在另一个类的定义内部,这就是内部类. 为什么要使用内部类?在<Think in java>中有这样一句话:使用内部类最吸引 ...

  3. linux系统编程:open常用参数详解

    open用于打开一个文件,通过设置不同的flag,可以让进程只读,只写,可读/可写等操作 一.对一个不存在或者存在的文件(test.txt),进行写入操作 /*==================== ...

  4. python MRO及c3算法

    1. 了解python2和python3类的区别 python2在2.3之前使用的是经典类, 2.3之后, 使用的是新式类 2. 经典类的MRO 树形结构的深度优先遍历 -> 树形结构遍历 cl ...

  5. 设计模式(13)--Chain of Responsibility(责任链模式)--行为型

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.模式定义: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一 ...

  6. js-权威指南学习笔记19

    第十九章 jQuery类库 1.传递HTML文本字符串给$()方法,jQuery会根据传入的文本创建好HTML元素并封装为jQuery对象返回. 2.想要遍历jQuery对象中的所有元素时,可以调用e ...

  7. postman获取全局

    1.获取token接口时,在test里面输入如下语句 postman.clearGlobalVariable("token"); var jsonData = JSON.parse ...

  8. Android 机器人项目Pepper_Android

    github地址:https://github.com/ohwada/Pepper_Android

  9. Cookie、Session 和 Token区别

    1 Cookie.Session 和 Token 都是用来做持久化处理的,目的就是让客户端和服务端相互认识.Http 请求默认是不持久的没有状态的,谁也不认识谁.   2 Cookie: 是存放在客户 ...

  10. window下安装RabbitMQ

    RabbitMQ: MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们.消 ...