题意:给定n*m的图,每个士兵可以占领当前行和列,第i行至少要R[i]个士兵占领,第j列至少要C[j]个士兵占领,部分网格无法占领,求占领所用最少士兵数,若无解则输出orz

士兵的贡献情况有1(只有效占领行/列),2(既占领行又占领列)

用最大流跑出贡献为2的士兵的个数,然后把所有要求相减处理就得出贡献为1的士兵个数

非法方案用极端情况和要求行列士兵数去考虑

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define iin(a) scanf("%d",&a)
#define lin(a) scanf("%lld",&a)
#define din(a) scanf("%lf",&a)
#define s0(a) scanf("%s",a)
#define s1(a) scanf("%s",a+1)
#define print(a) printf("%lld",(ll)a)
#define enter putchar('\n')
#define blank putchar(' ')
#define println(a) printf("%lld\n",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int MAXN = 1e6+11;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],cap[MAXN<<1],flow[MAXN<<1];
int head[MAXN],tot;
void init(){
memset(head,-1,sizeof head);
tot=0;
}
void add(int u,int v,int w){
to[tot]=v;
nxt[tot]=head[u];
cap[tot]=w;
flow[tot]=0;
head[u]=tot++;
swap(u,v);
to[tot]=v;
nxt[tot]=head[u];
cap[tot]=0;
flow[tot]=0;
head[u]=tot++;
}
int n,m,s,t;
int dis[MAXN],pre[MAXN],cur[MAXN],gap[MAXN];
bool vis[MAXN];
struct QUEUE{
int que[MAXN];
int front,rear;
void init(){front=rear=0;}
void push(int u){que[rear++]=u;}
int pop(){return que[front++];}
bool empty(){return front==rear;}
}que;
void bfs(){
memset(vis,0,sizeof vis);
que.init();
que.push(t);
vis[t]=1;dis[t]=0;
while(que.empty()^1){
int u = que.pop();
for(int i = head[u]; ~i; i = nxt[i]){
register int v=to[i],c=cap[i^1],f=flow[i^1];
if(!vis[v]&&c>f){
vis[v]=1;
dis[v]=dis[u]+1;
que.push(v);
}
}
}
}
int aug(){
int u=t,ans=INF;
while(u!=s){
ans=min(ans,cap[pre[u]]-flow[pre[u]]);
u=to[pre[u]^1];
}
u=t;
while(u!=s){
flow[pre[u]]+=ans;
flow[pre[u]^1]-=ans;
u=to[pre[u]^1];
}
return ans;
}
int isap(){
int ans=0;
bfs();
memset(gap,0,sizeof gap);
memcpy(cur,head,sizeof head);
for(int i = 1; i <= n; i++) gap[dis[i]]++;
int u = s;
while(dis[s]<n){
if(u==t){
ans+=aug();
u=s;
}
bool ok=0;
for(int i = cur[u]; ~i; i = nxt[i]){
int v=to[i],c=cap[i],f=flow[i];
if(c>f&&dis[u]==dis[v]+1){
ok=1;
pre[v]=i;
cur[u]=i;
u=v;
break;
}
}
if(!ok){
int mn=n-1;
for(int i = head[u]; ~i; i = nxt[i]){
int v=to[i],c=cap[i],f=flow[i];
if(c>f) mn=min(mn,dis[v]);
}
if(--gap[dis[u]]==0) break;
dis[u]=mn+1;gap[dis[u]]++;cur[u]=head[u];
if(u!=s) u=to[pre[u]^1];
}
}
return ans;
}
int r,c,k;
int R[233],C[333];
int block[233][333];
int haver[233],havec[233];
int main(){
while(cin>>r>>c>>k){
init(); int cnt=0;
memset(block,0,sizeof block);
memset(haver,0,sizeof haver);
memset(havec,0,sizeof havec);
rep(i,1,r) R[i]=read();
rep(i,1,c) C[i]=read();
rep(i,1,r) cnt+=R[i];
rep(i,1,c) cnt+=C[i];
rep(i,1,k){
int a=read();
int b=read();
block[a][b]=1;
}
s=r+c+1;t=s+1;n=t;
rep(i,1,r) add(s,i,R[i]);
rep(i,1,c) add(i+r,t,C[i]);
rep(i,1,r) rep(j,1,c){
if(!block[i][j]){
haver[i]++;
havec[j]++;
add(i,j+r,1);
}
}
bool flag=0;
rep(i,1,r) if(haver[i]<R[i]) flag=1;
rep(i,1,c) if(havec[i]<C[i]) flag=1;
if(flag){
printf("JIONG!\n");
continue;
}
ll ans=isap();
ll tmp=cnt-2*ans;
println(ans+tmp);
}
return 0;
}

BZOJ - 1458 / P4311 最大流应用 贪心的更多相关文章

  1. bzoj 1305 二分+最大流判定|贪心

    首先我们二分一个答案mid,在判定是否能举办mid次,那么对于每个次我们可以用最大流根据是否满流(流量为n*mid)来判定,对于每个点我们拆成两个点,分别表示这个人要和他喜欢和不喜欢的人一起跳舞,那么 ...

  2. [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆)

    [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆) 题面 给出一个长度为n的序列,选k段长度在L到R之间的区间,一个区间的值等于区间内所有元素之的和,使得k个区间的值之和最大.区 ...

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

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

  4. bzoj 1458: 士兵占领 -- 最大流

    1458: 士兵占领 Time Limit: 10 Sec  Memory Limit: 64 MB Description 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵 ...

  5. bzoj 1458 士兵占领(最大流)

    [题意] n行m列,第i行必须放L[i],第j列必须放C[j],有障碍格,求满足条件至少需要放多少. [思路] 至少放多少等价于最多不放多少. 对行列分别建XY点,则连边(S,Xi,a)(Yi,T,b ...

  6. bzoj 1458 网络流

    我们可以知道每行最多可以有多少个格子不用建点,设为x[i],每列同理设为y[i],那么我们连接(source,i,x[i]),(i,sink,y[i])表示我们将一个格子不建点,那么(i,j,flag ...

  7. ZOJ-2364 Data Transmission 分层图阻塞流 Dinic+贪心预流

    题意:给定一个分层图,即只能够在相邻层次之间流动,给定了各个顶点的层次.要求输出一个阻塞流. 分析:该题直接Dinic求最大流TLE了,网上说采用Isap也TLE,而最大流中的最高标号预流推进(HLP ...

  8. [BZOJ 1028] [JSOI2007] 麻将 【枚举+贪心判断】

    题目链接:BZOJ - 1028 题目分析 枚举听的是哪种牌,再枚举成对的是哪种牌,再贪心判断: 从1到n枚举每一种牌,如果这种牌的个数小于0,就返回不合法. 将这种牌的张数 % 3, 剩下的只能和 ...

  9. [BZOJ 1029] [JSOI2007] 建筑抢修 【贪心】

    题目链接:BZOJ - 1029 题目分析 使用一种贪心策略. 现将任务按照deadline从小到大排序. 然后枚举每一个任务,如果当前消耗的时间加上完成这个任务的时间不会超过这个任务的deadlin ...

随机推荐

  1. [GO]冒泡排序的原理和代码实现

    冒泡排序的原理:对于一个数组里所有的元素进行两两比较,发生大于则变换数组下标则为升序排序,发生小于则变换数据下标的则为降序排序 比如给定的数组为[1, -2, 3, -4],对于我们的需求,两两比较后 ...

  2. Requests接口测试(三)

    一.定制请求头 我们先来看一下,关于请求头的定制演示,相信了解http协议的小伙伴应该对请求头部headers请求头部并不陌生,那么作为实际工作中的我们,如果想自定义一些请求头的信息,我们应该怎么办呢 ...

  3. 问渠那得清如许?为有源头活水来。——java面向对象的思想

    20169205 2016-2017-2 <移动平台应用开发实践>第2周学习总结 教材学习内容总结 本次作业要求的部分主要是Java高级语言实现面向对象编程的基本方法,其中所介绍的面向对象 ...

  4. Java实现四则运算 谢雅淇 袁杏仪

    GitHub链接:https://github.com/3216004716/four-operations.git 项目相关要求 使用 -n 参数控制生成题目的个数,例如 Myapp.exe -n ...

  5. HTML5 Canvas核心技术:图形、动画与游戏开发 PDF扫描版​

    HTML5 Canvas核心技术:图形.动画与游戏开发 内容简介: <HTML5 Canvas核心技术:图形.动画与游戏开发>中,畅销书作家David Geary(基瑞)先生以实用的范例程 ...

  6. 转:[python] pip 升级所有的包

    pip 当前内建命令并不支持升级所有已安装的Python模块. 列出当前安装的包: pip list 列出可升级的包: pip list --outdate 升级一个包: pip install -- ...

  7. Python数据聚合和分组运算(1)-GroupBy Mechanics

    前言 Python的pandas包提供的数据聚合与分组运算功能很强大,也很灵活.<Python for Data Analysis>这本书第9章详细的介绍了这方面的用法,但是有些细节不常用 ...

  8. 【bzoj1014】: [JSOI2008]火星人prefix 平衡树-字符串-hash-二分

    [bzoj1014]: [JSOI2008]火星人 用平衡树维护字符串的hash 然后询问的时候二分一下就好了 /* http://www.cnblogs.com/karl07/ */ #includ ...

  9. kali linux之本地提权

    已实现本地低权限帐号登录,希望获取更高权限,实现对目标进一步控制 系统帐号之间权限隔离(操作系统安全的基础,用户空间,内核空间) 系统帐号(用户帐号登录时获取权限令牌,服务帐号无需用户登录已在后台启动 ...

  10. python 面向对象十一 super函数

    python 面向对象十一 super函数   super函数用来解决钻石继承. 一.python的继承以及调用父类成员 父类: class Base(object): def __init__(se ...