果然建图是关键。
拆点,拆出来两点之间连边,可增广量为柱子能承受的负荷,互相能跳的到的柱子,及距离在d以内的,从node2到node1连INF的边,源点到有lizards的位置连一条1的边,每个能跳出的柱子与汇点连一条INF的边。
这题输出有点坑,no和1的时候用was,其他的用were,汗!!!后来看到别人的题解才知道。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define INF 200000000
char s[25][25];
int n,m,d,map[505][505],first[1005],next[200005],flow[1005][1005],queue[100005],idx,lever[1005];
struct edge
{
int u;
int v;
int f;
}en[200005];
int min(int a,int b)
{
return a>b?b:a;
}
void add(int s,int t,int f)
{
idx++;
en[idx].u=s;
en[idx].v=t;
en[idx].f=f;
next[idx]=first[s];
first[s]=idx;
}
int bfs(int s)
{
int begin,end,x,i,j,k,l;
memset(lever,0,sizeof(lever));
lever[s]=1;
queue[0]=s;
begin=0;end=1;
while(begin!=end)
{
x=queue[begin];
begin++;
for(i=first[x];i!=-1;i=next[i])
{
if(lever[en[i].v]==0&&en[i].f>flow[x][en[i].v])
{
lever[en[i].v]=lever[x]+1;
queue[end]=en[i].v;
end++;
if(en[i].v==2*n*m+1)
return 1;
}
}
}
if(lever[2*n*m+1]==0)
return 0;
else
return 1;
}
int dfs(int s,int kuo)
{
int i,j,k,l,tmp,so;
if(s==2*n*m+1)
return kuo;
so=0;
for(i=first[s];i!=-1;i=next[i])
{
if(lever[en[i].v]==lever[s]+1&&en[i].f>flow[s][en[i].v])
{
tmp=dfs(en[i].v,min(en[i].f-flow[s][en[i].v],kuo));
if(tmp==0)
lever[en[i].v]=-1;
so+=tmp;
kuo-=tmp;
flow[s][en[i].v]+=tmp;
flow[en[i].v][s]-=tmp;
if(kuo==0)
break;
}
}
return so;
}
int main()
{
int i,j,k,l,t,mf,sum,count,qqq;
while(scanf("%d",&t)!=EOF)
{
count=0;
while(t--)
{
memset(first,-1,sizeof(first));
memset(next,-1,sizeof(next));
memset(flow,0,sizeof(flow));
scanf("%d%d",&n,&d);
idx=0;
for(i=0;i<n;i++)
scanf("%s",s[i]);
memset(map,0,sizeof(map));
m=strlen(s[0]);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
for(k=0;k<n;k++)
for(l=0;l<m;l++)
if(s[i][j]>'0'&&s[k][l]>'0'&&abs(i-k)+abs(j-l)<=d)
map[i*m+j+1][k*m+l+1]=1;
for(i=1;i<=n*m;i++)
for(j=1;j<=n*m;j++)
{
if(map[i][j]==1)
{
add(i+n*m,j,INF);
add(j,i+n*m,0);
}
}
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(s[i][j]>'0')
{
add(i*m+j+1,i*m+j+1+n*m,s[i][j]-'0');
add(i*m+j+1+n*m,i*m+j+1,0);
if(min(i+1,min(n-i,min(j+1,m-j)))<=d)
{
add(i*m+j+1+n*m,2*n*m+1,INF);
add(2*n*m+1,i*m+j+1+n*m,0);
}
}
}
for(i=0;i<n;i++)
scanf("%s",s[i]);
sum=0;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(s[i][j]=='L')
{
sum++;
add(0,i*m+j+1,1);
add(i*m+j+1,0,0);
}
}
}
mf=0;
while(bfs(0))
{
mf+=dfs(0,INF);
}
if(mf==sum)
printf("Case #%d: no lizard was left behind.\n",++count);
else if(sum-mf!=1)
printf("Case #%d: %d lizards were left behind.\n",++count,sum-mf);
else
printf("Case #%d: 1 lizard was left behind.\n",++count);
}
}
return 0;
}