S连“。”流量为1
二分答案 x
算出每一个门到每一个点的距离若小于x连边 流量为1
门连T 流量为 x
其实这个题完全不用拆点
因为门限制的流量为x
若有x个点和门的dis<x
每个点到门的距离肯定<=x
而且dis=x的点最多有一个
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#define T 99999
using namespace std;
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
int t[T];
int head[444],nxt[T],lst[T],v[T];
int id[33][33],mx[444],my[444];
int dis[33][33],q[T][2],S,W,h[T];
char s[33][33];int D[444];
int n,m,tot=1,cnt,top,pl,sum;
void insert(int x,int y,int z)
{
//cout << x <<" "<< y <<" "<< z << endl;
lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot; v[tot]=z;
lst[++tot]=x; nxt[tot]=head[y]; head[y]=tot; v[tot]=0;
}
void bfs(int xx,int yy,int f)
{
memset(dis,0,sizeof(dis));
int l=1,r=2; q[1][0]=xx,q[1][1]=yy;
while(l<r)
{
int x=q[l][0],y=q[l++][1];
for(int i=0;i<4;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(s[nx][ny]=='.')
{
if(!dis[nx][ny])
{
dis[nx][ny]=dis[x][y]+1;
if(dis[nx][ny]<=f)
{
q[r][0]=nx,q[r++][1]=ny;
insert(id[nx][ny],id[xx][yy],1);
}
}
}
}
}
}
bool BFS()
{
for(int i=1;i<=W;i++)D[i]=0;D[S]=1;
int l=1,r=2;h[1]=S;
while(l<r)
{
int x=h[l++];
for(int i=head[x];i;i=nxt[i])
if(v[i]>0&&!D[lst[i]])
{
D[lst[i]]=D[x]+1;
h[r++]=lst[i];
}
}
return D[W]!=0;
}
int dfs(int x,int f)
{
int ww=0,w;
if(x==W)return f;
for(int i=head[x];i;i=nxt[i])
if(v[i]&&D[lst[i]]==D[x]+1)
{
w=dfs(lst[i],min(v[i],f-ww));
ww+=w;v[i]-=w,v[i^1]+=w;
if(f==ww)return ww;
}
return ww;
}
bool jud(int x)
{
memset(head,0,sizeof(head));tot=1;
for(int i=1;i<=top;i++)bfs(mx[i],my[i],x);
//system("pause");
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='.')insert(S,id[i][j],1);
for(int i=1;i<=top;i++)insert(id[mx[i]][my[i]],W,x);
int ans=0;
while(BFS())ans+=dfs(S,T);
return ans==sum;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]!='X')
{
id[i][j]=++cnt;
if(s[i][j]=='D')
{
mx[++top]=i;
my[top]=j;
}
}
S=cnt+1,W=S+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='.')sum++;
int l=0,r=sum,ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(jud(mid))ans=mid,r=mid-1;
else l=mid+1;
}
if(!ans)printf("impossible");
else cout << ans;
}