BZOJ1458: 士兵占领
https://lydsy.com/JudgeOnline/problem.php?id=1458
分析:
- 先强制全都选上,然后求最多能删去几个。
- 然后就和正常的二分图匹配一样了。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
#define inf 0x3f3f3f3f
#define N 10050
#define M 500050
typedef double f2;
namespace Dinic {
int head[N],to[M],nxt[M],flow[M],dep[N],Q[N],cnt=1;
const int S=N-1,T=N-2;
inline void add(int u,int v,int f) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f;
to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0;
}
bool bfs() {
memset(dep,0,sizeof(dep));
int l=0,r=0; dep[S]=1;
Q[r++]=S;
while(l<r) {
int x=Q[l++],i;
for(i=head[x];i;i=nxt[i]) if(!dep[to[i]]&&flow[i]) {
dep[to[i]]=dep[x]+1; if(to[i]==T) return 1; Q[r++]=to[i];
}
}return 0;
}
int dfs(int x,int mf) {
if(x==T) return mf;
int i,nf=0;
for(i=head[x];i;i=nxt[i]) if(dep[to[i]]==dep[x]+1&&flow[i]) {
int tmp=dfs(to[i],min(mf-nf,flow[i]));
if(!tmp) dep[to[i]]=0;
nf+=tmp; flow[i]-=tmp; flow[i^1]+=tmp;
if(nf==mf) break;
}
return nf;
}
int dinic() {
int f=0,mxf=0;
while(bfs()) {
while((f=dfs(S,inf))) mxf+=f;
}return mxf;
}
}
int n,m,K,sum,L[105],C[105],sl[105],sc[105],vis[105][105];
int main() {
using namespace Dinic;
scanf("%d%d%d",&n,&m,&K);
int i,j,x,y;
for(i=1;i<=n;i++) scanf("%d",&L[i]);
for(i=1;i<=m;i++) scanf("%d",&C[i]);
for(i=1;i<=K;i++) {
scanf("%d%d",&x,&y); vis[x][y]=1;
}
for(i=1;i<=n;i++) {
for(j=1;j<=m;j++) {
sl[i]+=(!vis[i][j]);
}
if(sl[i]<L[i]) {puts("JIONG"); return 0;}
add(S,i,sl[i]-L[i]);
}
for(j=1;j<=m;j++) {
for(i=1;i<=n;i++) {
sc[j]+=(!vis[i][j]);
}
sum+=sc[j];
if(sc[j]<C[j]) {puts("JIONG"); return 0;}
add(j+n,T,sc[j]-C[j]);
}
for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(!vis[i][j])add(i,j+n,1);
printf("%d
",sum-dinic());
}