题目大意:给定一个m*n的棋盘,其中k个点有障碍,要求放置最少的士兵,使第i行有至少L[i]个,第j列有至少C[j]个
首先这种问题很明显的网络流 但是正图肯定是跑不了 限制条件是至少而且要求放置的也是最少 很难解决
反向考虑 将棋盘上先放满士兵 此时若不能满足条件则无解 然后求最多能撤掉多少个士兵 其中第i行最多撤去templ[i]-l[i]个士兵 templ[i]表示第i行当前放置的士兵个数
尼玛我的网络流是多久不写了……居然没连反向弧就跑样例……最逗的是数组开小一倍不报RE报WA……
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 110
#define s 0
#define t (m+n+1)
#define INF 0x3f3f3f3f
using namespace std;
struct abcd{
int to,f,next;
}table[M*M<<1];
int head[M+M],tot=1;
int m,n,k,ans;
int l[M],c[M];
int templ[M],tempc[M];
bool ban[M][M];
int d[M+M];
void Add(int x,int y,int z)
{
table[++tot].to=y;
table[tot].f=z;
table[tot].next=head[x];
head[x]=tot;
}
bool BFS()
{
int i;
static int q[65540];
static unsigned short r,h;
r=h=0;
memset(d,-1,sizeof d);
d[s]=0;q[++r]=s;
while(r!=h)
{
int x=q[++h];
for(i=head[x];i;i=table[i].next)
if(table[i].f)
{
if(~d[table[i].to])
continue;
d[table[i].to]=d[x]+1;
q[++r]=table[i].to;
if(table[i].to==t)
return true;
}
}
return false;
}
int Dinic(int x,int flow)
{
int i,left=flow;
if(x==t)
return flow;
for(i=head[x];i&&left;i=table[i].next)
if(table[i].f&&d[table[i].to]==d[x]+1)
{
int temp=Dinic(table[i].to,min(left,table[i].f));
if(!temp) d[table[i].to]=-1;
left-=temp;
table[i].f-=temp;
table[i^1].f+=temp;
}
return flow-left;
}
int main()
{
int i,j,x,y;
cin>>m>>n>>k;
for(i=1;i<=m;i++)
scanf("%d",&l[i]),templ[i]=n;
for(i=1;i<=n;i++)
scanf("%d",&c[i]),tempc[i]=m;
for(i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
if(--templ[x]<l[x])
{
puts("JIONG!");
return 0;
}
if(--tempc[y]<c[y])
{
puts("JIONG!");
return 0;
}
ban[x][y]=true;
}
ans=m*n-k;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
if(!ban[i][j])
Add(i,m+j,1),Add(m+j,i,0);
for(i=1;i<=m;i++)
Add(s,i,templ[i]-l[i]),Add(i,s,0);
for(i=1;i<=n;i++)
Add(m+i,t,tempc[i]-c[i]),Add(t,m+i,0);
while( BFS() )
ans-=Dinic(s,INF);
cout<<ans<<endl;
}