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; }