bzoj 1458 网络流

  我们可以知道每行最多可以有多少个格子不用建点,设为x[i],每列同理设为y[i],那么我们连接(source,i,x[i]),(i,sink,y[i])表示我们将一个格子不建点,那么(i,j,flag[i][j]),当i,j这个格子可以建点的时候连边表示我们不在这个格子建点,那么n*m-k-最大流就是答案。  

  因为我们考虑可以在哪一个位置不放点,使得整个矩阵仍然合法,这样我们就可以知道最多有多少个合法的不建点的合法格子。  

  备注:开始想写有下限的最小可行流的着。


/**************************************************************
Problem: 1458
User: BLADEVIL
Language: C++
Result: Accepted
Time:28 ms
Memory:1788 kb
****************************************************************/

//By BLADEVIL
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 400
#define maxm 30010
#define inf (~0U>>1)

using namespace std;

int n,m,k,source,sink,ans,l;
int need[maxn][2];
int flag[maxn][maxn];
int que[maxn],dis[maxn],last[maxn],pre[maxm],other[maxm],len[maxm];

void connect(int x,int y,int z) {
pre[++l]=last[x];
last[x]=l;
other[l]=y;
len[l]=z;
//if (z) printf("%d %d %d\n",x,y,z);
}

int bfs() {
memset(dis,0,sizeof dis);
que[1]=source; dis[source]=1;
int h(0),t(1);
while (h<t) {
int cur(que[++h]);
for (int p=last[cur];p;p=pre[p]) {
if (dis[other[p]]) continue;
if (!len[p]) continue;
dis[other[p]]=dis[cur]+1;
que[++t]=other[p];
if (other[p]==sink) return 1;
}
}
return 0;
}

int dinic(int x,int flow) {
if (x==sink) return flow;
int rest=flow;
for (int p=last[x];p;p=pre[p]) {
if (!len[p]) continue;
if (dis[other[p]]!=dis[x]+1) continue;
if ((!rest)||(!len[p])) continue;
int tmp=dinic(other[p],min(rest,len[p]));
if (!tmp) dis[other[p]]=0;
len[p]-=tmp; len[p^1]+=tmp; rest-=tmp;
}
return flow-rest;
}

int main() {
scanf("%d%d%d",&n,&m,&k); l=1;
for (int i=1;i<=n;i++) scanf("%d",&need[i][0]),need[i][0]=m-need[i][0];
for (int i=1;i<=m;i++) scanf("%d",&need[i][1]),need[i][1]=n-need[i][1];
for (int i=1;i<=k;i++) {
int x,y; scanf("%d%d",&x,&y);
flag[x][y]=1;
need[x][0]--; need[y][1]--;
}
for (int i=1;i<=n;i++) if (need[i][0]<0) {
printf("JIONG!\n");
return 0;
}
for (int i=1;i<=m;i++) if (need[i][1]<0) {
printf("JIONG!\n");
return 0;
}
source=n+m+2; sink=source+1;
for (int i=1;i<=n;i++) connect(source,i,need[i][0]),connect(i,source,0);
for (int i=1;i<=m;i++) connect(i+n,sink,need[i][1]),connect(sink,i+n,0);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) if (!flag[i][j])
connect(i,j+n,1),connect(j+n,i,0);
ans=n*m-k;
while (bfs()) ans-=dinic(source,inf);//,printf("%d\n",ans);
printf("%d\n",ans);
return 0;
}

bzoj 1458 网络流

时间: 2024-10-22 22:38:07

bzoj 1458 网络流的相关文章

[bzoj 1458] 士兵占领(网络流dinic)

1458: 士兵占领 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 784  Solved: 458[Submit][Status][Discuss] Description 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵.现在你的任务是要求使用最少个数的士兵来占领整个棋盘.

[BZOJ 1458]士兵占领(网络流)

Description 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵.现在你的任务是要求使用最少个数的士兵来占领整个棋盘. Solution 可以用上下界最小流来做,不过我觉得黄学长的这个思路也很直接 将每行每列都看成一个点,由s向行连边,容量为可以放置的士兵数-至少放置的士兵数 由列向t连边,容量为可以放置的士兵数-至少

【BZOJ 1458】 士兵占领

1458: 士兵占领 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 632 Solved: 366 [Submit][Status][Discuss] Description 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵.现在你的任务是要求使用最少个数的士兵来占领整个棋盘.

BZOJ 1458 士兵占领 Dinic最大流

题目大意:给定一个m*n的棋盘,其中k个点有障碍,要求放置最少的士兵,使第i行有至少L[i]个,第j列有至少C[j]个 首先这种问题很明显的网络流 但是正图肯定是跑不了 限制条件是至少而且要求放置的也是最少 很难解决 反向考虑 将棋盘上先放满士兵 此时若不能满足条件则无解 然后求最多能撤掉多少个士兵 其中第i行最多撤去templ[i]-l[i]个士兵 templ[i]表示第i行当前放置的士兵个数 尼玛我的网络流是多久不写了--居然没连反向弧就跑样例--最逗的是数组开小一倍不报RE报WA-- #i

bzoj 1066(网络流)

题意 思路:网络流分类里面的题目..所以自然要想网络流啦...由题意可知:蜥蜴在高度>0的柱子上才有行动能力..所以只要考虑高度大于0的柱子即可..以图的每根柱子作为点,对于柱子u,如果u能到达的柱子v,就连接(u , v).如果是边有高度..那么选定一个起点s连接所有蜥蜴的起点,权值设为1.所有能跳出边界的点连接终点t,权值设为inf.容量1代表这条边被经过一次.这样这个图能跳出去的蜥蜴数量就是从s->t的最大流.但是这个图是每个点有容量限制.这种我们可以把点拆成两个.拆点之后得到的两点,假

BZOJ 1458 士兵占领

http://www.lydsy.com/JudgeOnline/problem.php?id=1458 题意:n x m的棋盘,k个位置不能放,每行和每列都有要求至少的士兵,求能否有最少的满足条件的士兵放法是多少. 思路:先全放满求能否满足,再尽量删掉士兵: 对于每行:能放m[i],至少放c[i],就从S连向i:m[i]-c[i],代表能删的最大 对于每列:能放m[i],至少放c[i],就从i+n连向T:m[i]-c[i],代表能删的最大 这样对于i,j这个位置如果可以放士兵,那就从i行连向j

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

1458: 士兵占领 Time Limit: 10 Sec  Memory Limit: 64 MB Description 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵.现在你的任务是要求使用最少个数的士兵来占领整个棋盘. Input 第一行两个数M, N, K分别表示棋盘的行数,列数以及障碍的个数. 第二行有M个数表示

bzoj网络流

近期看了一些bzoj的网络流,深感智商不够.不过对于网络流又有了进一步的理解. 还是mark一下吧. 献上几篇论文:1)<最小割模型在信息学竞赛中的应用> 2)<浅析一类最小割问题> 1.bzoj1066(最大流) 题意:戳这里 思路:很明显拆点最大流模型,然后对于每个点每个高度流量限为1,那么根据最大流即为可以出去的蜥蜴的数量. 2.bzoj1077(费用流) 戳这里 3.bzoj1391(最小割) 题意:戳这里 思路:有点像最大权闭合图..可以利用最小割的性质建图: <S

[NetworkFlow]网络流建模相关

流 网络流问题本质上是线性规划问题的应用之一,线性规划问题的标准形式是给出一组等式约束和不等式约束,要求最优化一个线性函数. 在流问题中,变量以流量的形式出现在问题中,我们给出一个流网络(以有向图的形式)来解决有关流的问题. 流是整个网络流问题的核心所在,它实际上是定义在流网络上的一个线性函数,在流网络中,每条边都有一个流量f(u,v),流f=∑v∈Vf(S,v) 流量f(u,v)是流问题中的变量,它有两个约束,一个是不等式,一个是等式 (1)容量限制:f(u,v)≤c(u,v) (2)流量平衡