第一次这样建图 每秒一层···每层的点拆成2个 一个出 一个入 容量为1,建图很麻烦 ···
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int const ncnt = 200000;
struct edge
{
int u,v,flow,next;
}e[1000000];int ecnt;
int n,m;
char map[20][20];
int head[ncnt];
int const inf = 1<<30;
int abs(int a)
{
return a>0 ? a : -a;
}
void addedge(int u,int v,int flow)
{
e[ecnt].u = u;
e[ecnt].v = v;
e[ecnt].flow = flow;
e[ecnt].next = head[u];
head[u] = ecnt++;
e[ecnt].u = v;
e[ecnt].v = u;
e[ecnt].flow = 0;
e[ecnt].next = head[v];
head[v] = ecnt++;
}
int pre[ncnt],cur[ncnt],gap[ncnt],dis[ncnt];
int sap(int s,int t)
{
int flow = 0,aug = inf,u;
bool flag;
for(int i=0; i<=t; i++)
cur[i]=head[i],gap[i]=dis[i]=0;
gap[0] = t+1;
u = pre[s] = s;
while(dis[s]<t+1)
{
flag = false;
for(int &j=cur[u]; j!=-1; j=e[j].next)
{
int v = e[j].v;
if(e[j].flow>0&&dis[u]==dis[v]+1)
{
flag = true;
if(aug > e[j].flow) aug = e[j].flow;
pre[v] = u;
u = v;
if(u==t)
{
flow+=aug;
while(u!=s)
{
u = pre[u];
e[cur[u]].flow -= aug;
e[cur[u]^1].flow += aug;
}
aug = inf;
}
break;
}
}
if(flag) continue;
int mindis = t+1;
for(int j = head[u]; j!=-1; j=e[j].next)
{
int v = e[j].v;
if(e[j].flow > 0 && dis[v] < mindis )
mindis = dis[v],cur[u] = j;
}
if((--gap[dis[u]])==0) return flow;
gap[dis[u] = mindis + 1 ]++;
u = pre[u];
}
return flow;
}
int ans;
void init(int mid)
{
memset(head,-1,sizeof(head));ecnt = 0;
int down = 2*n*m;
int ff = n*m;
for(int k=0;k<mid;k++)
{
int cnt = k*2*n*m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(k==0&&map[i][j]=='X')
addedge(0,cnt+i*m+j+1,1);
if(map[i][j]=='@') addedge(cnt+i*m+j+1,cnt+i*m+j+1+ff,1),addedge(cnt+i*m+j+1+ff,mid*2*n*m+n*m+1,1);
else if(map[i][j]!='#')
{
addedge(cnt+i*m+j+1,cnt+i*m+j+1+ff,1);
addedge(cnt+i*m+j+1+ff,cnt+i*m+j+1+down,1);
if(i!=0&&map[i-1][j]!='#')
addedge(cnt+i*m+j+1+ff,cnt+(i-1)*m+j+1+down,1);
if(i!=n-1&map[i+1][j]!='#')
addedge(cnt+i*m+j+1+ff,cnt+(i+1)*m+j+1+down,1);
if(j!=0&&map[i][j-1]!='#')
addedge(cnt+i*m+j+1+ff,cnt+i*m+j-1+1+down,1);
if(j!=m-1&&map[i][j+1]!='#')
addedge(cnt+i*m+j+1+ff,cnt+i*m+j+1+1+down,1);
}
}
}
}
int solve(int mid)
{
init(mid);
return sap(0,mid*2*n*m+n*m+1);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
ans = 0;
for(int i=0;i<n;i++)
{
scanf("%s",map[i]);
for(int j=0;j<m;j++)
if(map[i][j]=='X')ans++;
}
int left=0,right=ans*2+1;
int now;
int ans1 = 0;
while(left<right)
{
int mid = (left+right)>>1;
now = solve(mid);
if(now < ans)
left = mid + 1;
else
ans1=mid-1,right = mid;
}
if(ans1!=0)
printf("%d\n",ans1);
else
printf("-1\n");
}
}