这道题目就是拆点,给出是每个点的容量限制,每个点如果可以escape就对汇点连条inf,每个点对可到的柱子连条inf,源点到有lizard的地方连条长为1的边,ans就是sum(lizard)-最大流
#include<cstdio>
#include<cstring>
int T,n,d,m,cnt,dis[1000],gap[1000],head[1000],s,t,sum,N;
const int inf=10000000;
struct EDGE
{
int to,f,nxt;
}edge[300000];
char g[30][30],gg[30][30],x[30][30];
int dx[]={1,1,-1,-1};
int dy[]={1,-1,1,-1};
int min(int a,int b)
{
return a<b?a:b;
}
void add(int x,int y,int c)
{
edge[cnt].to=y;
edge[cnt].f=c;
edge[cnt].nxt=head[x];
head[x]=cnt++;
}
void gao(int x,int y,int c)
{
add(x,y,c);
add(y,x,0);
}
int safe(int a,int b)
{
return a-d<=0||a+d>=n+1||b-d<=0||b+d>=m+1;
}
int in(int a,int b)
{
return a>=1&&a<=n&&b>=1&&b<=m;
}
void init()
{
memset(head,-1,sizeof(head));
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
sum=cnt=0;
}
int dfs(int x,int flow)
{
if(x==t)
return flow;
int temp=flow;
int pos=t-1;
int j;
for(j=head[x];j!=-1;j=edge[j].nxt)
{
int y=edge[j].to;
int c=edge[j].f;
if(c>0&&dis[x]==dis[y]+1)
{
int temp_flow=dfs(y,min(temp,c));
temp-=temp_flow;
edge[j].f-=temp_flow;
edge[j^1].f+=temp_flow;
if(temp==0||dis[s]==t)
return flow-temp;
}
if(c>0&&pos>dis[y])
pos=dis[y];
}
if(temp==flow)
{
if(!(--gap[dis[x]]))
dis[s]=t;
else
gap[dis[x]=pos+1]++;
}
return flow-temp;
}
int sap()
{
int maxflow=0;
gap[0]=t;
while(dis[s]<t)
{
maxflow+=dfs(s,inf);
}
return sum-maxflow;
}
int main()
{
int pro=0;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&d);
init();
for(int i=1;i<=n;i++)
scanf("%s",g[i]+1);
m=strlen(g[1]+1);
N=n*m;
s=2*N+1,t=s+1;
for(int i=1;i<=n;i++)
scanf("%s",gg[i]+1);
int k1=0,k2=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int num=(i-1)*m+j;
if(safe(i,j))
gao(num+N,t,inf);
if(g[i][j]-'0')
gao(num,num+N,g[i][j]-'0');
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(gg[i][j]=='L')
{
int num=(i-1)*m+j;
sum++;
gao(s,num,1);
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int num=(i-1)*m+j;
for(int z=0;z<4;z++)
for(int k1=0;k1<=d;k1++)
for(int k2=0;k2<=d;k2++)
if(k1+k2>0&&k1+k2<=d)
{
int x=i+k1*dx[z];
int y=j+k2*dy[z];
int mun=(x-1)*m+y;
if(in(x,y))
gao(num+N,mun,inf);
}
}
int ans=sap();
if(ans>1)printf("Case #%d: %d lizards were left behind.\n",++pro,ans);
else if(ans)printf("Case #%d: %d lizard was left behind.\n",++pro,ans);
else printf("Case #%d: no lizard was left behind.\n",++pro);
}
return 0;
}