[BZOJ1458]士兵占领

Posted by Dispwnl on March 1, 2019

题目

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

题解

有源汇上下界最小流板子充数的我真是嗨到不行啊

代码

# include<iostream>
# include<cstring>
# include<cstdio>
# include<algorithm>
using namespace std;
const int MAX=1e5+5,N=105,inf=1e8;
struct p{
	int x,y,dis;
}c[MAX];
int n,m,num=1,k,t,ss,tt;
int h[MAX],H[MAX],qu[MAX],d[MAX],f[MAX];
bool use[MAX];
bool qwq[N][N];
int read()
{
	int x(0);
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);x=x*10+ch-48,ch=getchar());
	return x;
}
bool bfs(int s,int t)
{
	qu[1]=s;
	memset(d,0,sizeof(d));
	int hl=1,tl=d[s]=1;
	while(hl<=tl)
	{
		int tt=qu[hl++];
		for(int i=h[tt];i;i=c[i].x)
		  if(c[i].dis&&!d[c[i].y])
		  {
		  	d[c[i].y]=d[tt]+1,qu[++tl]=c[i].y;
		  	if(c[i].y==t) return 1;
		  }
	}
	return 0;
}
int dfs(int x,int t,int dix=inf)
{
	if(x==t||!dix) return dix;
	int sum=0;
	for(int &i=H[x],dis;i;i=c[i].x)
	  if(d[c[i].y]==d[x]+1&&c[i].dis)
	  {
	  	dis=dfs(c[i].y,t,min(dix,c[i].dis));
	  	if(dis)
	  	{
	  		sum+=dis,dix-=dis,c[i].dis-=dis,c[i^1].dis+=dis;
	  		if(!dix) break;
		}
	  }
	if(!sum) d[x]=-2;
	return sum;
}
int Dinic(int s,int t)
{
	int tot=0,D;
	while(bfs(s,t))
	{
		memcpy(H,h,sizeof(h));
		while(D=dfs(s,t)) tot+=D;
	}
	return tot;
}
void add(int x,int y,int dis)
{
	c[++num]=(p){h[x],y,dis},h[x]=num;
	c[++num]=(p){h[y],x},h[y]=num;
}
int main()
{
	n=read(),m=read(),k=read(),t=n+m+1,ss=t+1,tt=ss+1;
	for(int i=1,x;i<=n;++i)
	  x=read(),add(0,i,inf-x),f[i]+=x,f[0]-=x;
	for(int i=n+1,x;i<=n+m;++i)
	  x=read(),add(i,t,inf-x),f[i]-=x,f[t]+=x;
	for(int i=1;i<=k;++i)
	  qwq[read()][read()]=1;
	for(int i=1;i<=n;++i)
	  for(int j=1;j<=m;++j)
	    if(!qwq[i][j]) add(i,n+j,1);
	for(int i=0;i<=t;++i)
	  if(f[i]<0) add(i,tt,-f[i]);
	  else add(ss,i,f[i]);
	add(t,0,inf),Dinic(ss,tt);
	for(int i=h[ss];i;i=c[i].x)
	  if(c[i].dis) return printf("JIONG!"),0;
	for(int i=h[tt];i;i=c[i].x)
	  if(c[i^1].dis) return printf("JIONG!"),0;
	return printf("%d",inf-Dinic(t,0)),0;
}