题目描述

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

输入

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

输出

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

样例输入

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

样例输出

4


题解

有源汇有上下界网络流最小流

s向每个代表第i行的点连一条下界为li,上界为inf的边。

每个代表第i列的点向t连一条下界为ci,上界为inf的边。

对于每个没有障碍的点,该点所在行向该点所在列连一条下界为0,上界为1的边。

这样把原题中的行列转化为网络流中的点,原图中的点转化为网络流中的边。

然后跑最小流即可。

求最小流步骤:

1.求可行流并判断是否满流,若不满流,则无解。

2.记录自己连的t->s的边的流量为ans1。

3.删除与SS或TT相连的边,删除自己连的t->s的边。

4.交换s和t,即以t为源点,s为汇点求最大流为ans2,得最小流为ans1-ans2。

#include <cstdio>
#include <cstring>
#include <queue>
#define inf 0x3fffffff
using namespace std;
queue<int> q;
int head[210] , to[30000] , val[30000] , next[30000] , cnt = 1 , in[210] , dis[210] , s , t;
bool map[110][110];
void add(int x , int y , int z)
{
to[++cnt] = y;
val[cnt] = z;
next[cnt] = head[x];
head[x] = cnt;
}
bool bfs()
{
int x , i;
while(!q.empty()) q.pop();
memset(dis , 0 , sizeof(dis));
dis[s] = 1 , q.push(s);
while(!q.empty())
{
x = q.front() , q.pop();
for(i = head[x] ; i ; i = next[i])
{
if(val[i] && !dis[to[i]])
{
dis[to[i]] = dis[x] + 1;
if(to[i] == t) return 1;
q.push(to[i]);
}
}
}
return 0;
}
int dinic(int x , int low)
{
if(x == t) return low;
int temp = low , i , k;
for(i = head[x] ; i ; i = next[i])
{
if(val[i] && dis[to[i]] == dis[x] + 1)
{
k = dinic(to[i] , min(temp , val[i]));
if(!k) dis[to[i]] = 0;
val[i] -= k , val[i ^ 1] += k;
if(!(temp -= k)) break;
}
}
return low - temp;
}
int main()
{
int n , m , k , i , j , x , y , tempcnt , sum = 0 , ans;
scanf("%d%d%d" , &n , &m , &k);
s = 0 , t = n + m + 1;
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &x) , add(s , i , inf) , add(i , s , 0) , in[s] -= x , in[i] += x;
for(i = 1 ; i <= m ; i ++ ) scanf("%d" , &x) , add(i + n , t , inf) , add(t , i + n , 0) , in[i + n] -= x , in[t] += x;
while(k -- ) scanf("%d%d" , &x , &y) , map[x][y] = 1;
for(i = 1 ; i <= n ; i ++ )
for(j = 1 ; j <= m ; j ++ )
if(!map[i][j])
add(i , j + n , 1) , add(j + n , i , 0);
add(t , s , inf) , tempcnt = cnt , add(s , t , 0);
s = n + m + 2 , t = n + m + 3;
for(i = 0 ; i <= n + m + 1 ; i ++ )
{
if(in[i] > 0) add(s , i , in[i]) , add(i , s , 0) , sum += in[i];
else add(i , t , -in[i]) , add(t , i , 0);
}
while(bfs()) sum -= dinic(s , inf);
if(sum)
{
printf("JIONG!\n");
return 0;
}
ans = val[tempcnt ^ 1];
for(i = s ; i ; i = next[i]) val[i] = val[i ^ 1] = 0;
for(i = t ; i ; i = next[i]) val[i] = val[i ^ 1] = 0;
val[tempcnt] = val[tempcnt ^ 1] = 0;
s = n + m + 1 , t = 0;
while(bfs()) ans -= dinic(s , inf);
printf("%d\n" , ans);
return 0;
}

【bzoj1458】士兵占领 有上下界最小流的更多相关文章

  1. BZOJ1458:士兵占领(有上下界最小流)

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

  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. jdbc学习笔记02

    数据库连接池 DBCP DataBase Conection Pool:数据库连接池 如果没有数据库连接池,每一次业务都需要服务器和数据库服务器建立一次连接,业务处理完连接断开,如果有1万次业务处理, ...

  2. ubuntu系统快速搭建开发环境

    1.免密登陆 1.1 原理 ssh协议中用到了对称加密和非对称加密,如果不了解可以百度一下,原理引用一下这篇博客 在ssh中,非对称加密被用来在会话初始化阶段为通信双方进行会话密钥的协商.由于非对称加 ...

  3. vue组件的基本知识点

    1. 组件中 is 的特性: 有些 HTML 元素,诸如 <ul>.<ol>.<table> 和 <select>,对于哪些元素可以出现在其内部是有严格 ...

  4. ECSHOP和SHOPEX快递单号查询国际EMS插件V8.6专版

    发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...

  5. php PHPEXcel导出

    1获取数据,2组装数据,3生成文件. 注意:无法使用ajax生成导出. $settlement = \Yii::$app->request->get('settlement'); $sav ...

  6. CacheManager源码分析

    计算rdd的某个分区是从RDD的iterator()方法开始的,我们从这个方法进入 然后我们进入getOrCompute()方法中看看是如何进行读取数据或计算的 getOrElseUpdate()方方 ...

  7. hadoop生态搭建(3节点)-01.基础配置

    # 基础配置# ==================================================================node1 vi /etc/hostname nod ...

  8. hadoop生态搭建(3节点)-06.hbase配置

    # http://archive.apache.org/dist/hbase/1.2.4/ # ==================================================== ...

  9. elasticsearch 5.x 系列之三 mapping 映射的时候的各个字段的设置

    首先看来创建一个mapping 来show show: curl -XPUT "master:9200/zebra_info?pretty" -H 'Content-Type: a ...

  10. Ubuntu装完后要做的几件事

    Ubuntu装完后要做的几件事 改hosts 无论哪里,改hosts都是第一件事,没hosts咋google.没google咋活.在终端输入命令 sudo gedit /etc/hosts在# The ...