#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=105,M=250005,inf=0x3f3f3f3f,s=10001,t=10002;
int cnt=1,head[N*N],flowa[N*N],dis[N*N],l[N],c[N],pre[2*N*N];
int idl[N][N],lst[N*N],tot,result,maxflow,total,m,n,k;
bool mapl[N][N],vis[N*N];
inline int read()
{
int w=1,f=0;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
w=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
f=f*10+c-'0';
c=getchar();
}
return w*f;
}
inline int minn(int a,int b)
{
if(a<b)
return a;
else
return b;
}
struct edge
{
int next,u,v,w,c;
}e[M<<1];
void addedge(int u,int v,int w,int c)
{
e[++cnt].next=head[u];
head[u]=cnt;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].c=c;
}
bool SPFA()
{
memset(dis,inf,sizeof(dis));
memset(vis,false,sizeof(vis));
memset(flowa,inf,sizeof(flowa));
queue<int> Q;
Q.push(s);
dis[s]=0;
vis[s]=true;
pre[t]=-1;
while(!Q.empty())
{
int u=Q.front();
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(e[i].w&&dis[v]>dis[u]+e[i].c)
{
dis[v]=dis[u]+e[i].c;
lst[v]=i;
pre[v]=u;
flowa[v]=minn(flowa[u],e[i].w);
if(!vis[v])
{
vis[v]=true;
Q.push(v);
}
}
}
vis[u]=false;
Q.pop();
}
return pre[t]!=-1;
}
void Dinic()
{
while(SPFA())
{
int u=t;
maxflow+=flowa[t];
result+=flowa[t]*dis[t];
while(u!=s)
{
e[lst[u]].w-=flowa[t];
e[lst[u]^1].w+=flowa[t];
u=pre[u];
}
}
}
int main()
{
int x,y;
n=read();m=read();k=read();
for(int i=1;i<=n;i++)
{
l[i]=read();
total+=l[i];
}
for(int i=1;i<=m;i++)
{
c[i]=read();
total+=c[i];
}
for(int i=1;i<=k;i++)
{
x=read();y=read();
mapl[x][y]=true;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
idl[i][j]=++tot;
for(int i=1;i<=n;i++)
if(l[i]>0)
{
addedge(idl[i][m],t,l[i],0);
addedge(t,idl[i][m],0,0);
}
for(int i=1;i<=m;i++)
if(c[i]>0)
{
addedge(idl[n][i],t,c[i],0);
addedge(t,idl[n][i],0,0);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(!mapl[i][j])
{
addedge(s,idl[i][j],2,1);
addedge(idl[i][j],s,0,-1);
if(j!=m)
{
addedge(idl[i][j],idl[i][m],1,0);
addedge(idl[i][m],idl[i][j],0,0);
}
if(i!=n)
{
addedge(idl[i][j],idl[n][j],1,0);
addedge(idl[n][j],idl[i][j],0,0);
}
}
}
Dinic();
/*
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
printf("*%d ",idl[i][j]);
}
printf("\n");
}
*/
for(int i=head[s];i;i=e[i].next)
{
printf("*%d %d\n",e[i].v,e[i].w);
if(e[i].w==0)
result--;
}
if(maxflow<total)
printf("JIONG!");
else
printf("%d",result);
return 0;
}
思路是对于每个没有障碍的点,由超级源点向他连流量为2,费用为1的边,对于每一个在行/列末尾的点,向超级汇点连一条容量为该行要求容量的边,最后把流量为2的点减去一次贡献
这破烂玩意已经调了n久了,求助\fad
我菜死了