题目
做法
考虑最多能删的点
\(S\)向每行所代表的点连(该行最多能删的点)容量的边,每列向\(T\)连(同理)的边
每个存在的格子\((x,y)\),\(x\)向\(y\)连\(1\)容量的边
My complete code
#include<bits/stdc++.h>
#include<queue>
using namespace std;
typedef int LL;
const LL maxn=1e5+9,inf=0x3f3f3f3f;
struct node{
LL to,next,f;
}dis[maxn];
LL num,S,T,n,m,k;
LL head[309],L[109],R[109],del[109][2],lev[309];
bool visit[109][109],mark[309];
inline void Add(LL u,LL v,LL f){
dis[++num]=(node){v,head[u],f}, head[u]=num;
}
inline LL Bfs(){
queue<LL> que; que.push(S);
memset(lev,0,sizeof(lev)),memset(mark,false,sizeof(mark));;
mark[S]=true;
while(que.size()){
LL u(que.front()); que.pop();
for(LL i=head[u];~i;i=dis[i].next){
LL v(dis[i].to);
if(!mark[v] && dis[i].f){
lev[v]=lev[u]+1;
mark[v]=true;
que.push(v);
}
}
}return mark[T];
}
LL Dfs(LL u,LL f){
if(u==T) return f;
LL tmp(f),now;
for(LL i=head[u];~i;i=dis[i].next){
LL v(dis[i].to);
if(tmp && dis[i].f && lev[v]==lev[u]+1){
if(now=Dfs(v,min(tmp,dis[i].f))){
dis[i].f-=now, dis[i^1].f+=now;
tmp-=now;
}else lev[v]=-1;
}
if(!tmp) break;
}return f-tmp;
}
inline void Dinic(){
LL ans(0);
while(Bfs())
ans+=Dfs(S,inf);
printf("%d",n*m-k-ans);
}
int main(){
cin>>n>>m>>k;
memset(head,-1,sizeof(head)), num=-1;
for(LL i=1;i<=n;++i) cin>>L[i];
for(LL i=1;i<=m;++i) cin>>R[i];
for(LL i=1;i<=k;++i){
LL x,y; cin>>x>>y;
visit[x][y]=true;
++del[x][0], ++del[y][1];
}
for(LL i=1;i<=n;++i)
for(LL j=1;j<=m;++j)
if(!visit[i][j]){
Add(i,j+n,1), Add(j+n,i,0);
}
S=n+m+1, T=S+1;
for(LL i=1;i<=n;++i){
LL now(m-del[i][0]-L[i]);
if(now<0){
printf("JIONG!");
return 0;
}
Add(S,i,now), Add(i,S,0);
}
for(LL i=1;i<=m;++i){
LL now(n-del[i][1]-R[i]);
if(now<0){
printf("JIONG!");
return 0;
}
Add(i+n,T,now), Add(T,i+n,0);
}
Dinic();
return 0;
}