先由S向每个有人的点连一条容量为1的边,然后二分时间t,对于每个每个门拆成t个点,每个点向T和下一个时间的点分别连容量为1和inf的边,表示这个门可以在每个时间里出来一个人,多余的人等到下一个时间
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<cassert>
5 #include<cstring>
6 #include<algorithm>
7 #define maxn 160000
8 #define maxm 400000
9 #define inf 1061109567
10 using namespace std;
11 char ch;
12 bool ok;
13 void read(int &x){
14 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
15 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
16 if (ok) x=-x;
17 }
18 char graph[22][22];
19 int n,m,cnt,pos[22][22],l,r,mid;
20 struct flow{
21 int s,t,idx,tot,now[maxn],son[maxm],pre[maxm],val[maxm];
22 int dis[maxn],head,tail,list[maxn];
23 bool bo[maxn];
24 void init(){s=0,t=1,idx=1,tot=1,memset(now,0,sizeof(now));}
25 void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
26 void add(int a,int b,int c){put(a,b,c),put(b,a,0);}
27 bool bfs(){
28 memset(bo,0,sizeof(bo));
29 head=0,tail=1,list[1]=s,bo[s]=1,dis[s]=0;
30 while (head<tail){
31 int u=list[++head];
32 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
33 if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v;
34 }
35 return bo[t];
36 }
37 int dfs(int u,int rest){
38 if (u==t) return rest;
39 int ans=0;
40 for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])
41 if (val[p]&&dis[v]==dis[u]+1){
42 int d=dfs(v,min(rest,val[p]));
43 val[p]-=d,val[p^1]+=d,ans+=d,rest-=d;
44 }
45 if (!ans) dis[u]=-1;
46 return ans;
47 }
48 int dinic(){
49 int ans=0;
50 while (bfs()) ans+=dfs(s,inf);
51 return ans;
52 }
53 }f,tmp;
54 struct Point{
55 int x,y,id;
56 }list[405];
57 int head,tail,g[405][405],dep[42][42];
58 bool bo[42][42],flag;
59 const int dx[4]={1,0,-1,0};
60 const int dy[4]={0,1,0,-1};
61 void bfs(int x,int y,int id){
62 memset(bo,0,sizeof(bo));
63 head=0,tail=1,list[1]=(Point){x,y,0},bo[x][y]=1,dep[x][y]=0;
64 while (head<tail){
65 Point p=list[++head];
66 int d=dep[p.x][p.y];
67 if (d) g[p.id][id]=d;
68 for (int i=0;i<4;i++){
69 int xx=p.x+dx[i],yy=p.y+dy[i];
70 if (xx<=0||xx>n||yy<=0||yy>m||graph[xx][yy]!=‘.‘||bo[xx][yy]) continue;
71 list[++tail]=(Point){xx,yy,pos[xx][yy]},bo[xx][yy]=1,dep[xx][yy]=d+1;
72 }
73 }
74 }
75 bool check(int lim){
76 f=tmp;
77 for (int i=2;i<=f.idx;i++) for (int j=1;j<=cnt;j++) if (g[i][j]<=lim&&g[i][j])
78 f.add(i,f.idx+cnt*(g[i][j]-1)+j,1);
79 for (int i=1;i<=cnt;i++) for (int j=1;j<=lim;j++){
80 f.add(f.idx+cnt*(j-1)+i,f.t,1);
81 if (j!=lim) f.add(f.idx+cnt*(j-1)+i,f.idx+cnt*j+i,inf);
82 }
83 return f.dinic()==f.idx-1;
84 }
85 int main(){
86 read(n),read(m),f.init();
87 for (int i=1;i<=n;i++) scanf("%s",graph[i]+1);
88 for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
89 if (graph[i][j]==‘.‘) pos[i][j]=++f.idx,f.add(f.s,f.idx,1);
90 else if (graph[i][j]==‘D‘) pos[i][j]=++cnt;
91 for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (graph[i][j]==‘D‘) bfs(i,j,pos[i][j]);
92 for (int i=2;i<=f.idx;i++){
93 bool fuck=1;
94 for (int j=1;j<=cnt;j++) if (g[i][j]!=0) fuck=0;
95 if (fuck){flag=1;break;}
96 }
97 if (flag){puts("impossible");return 0;}
98 for (tmp=f,l=1,r=400,mid=(l+r)>>1;l<r;mid=(l+r)>>1) if (check(mid)) r=mid; else l=mid+1;
99 printf("%d\n",l);
100 return 0;
101 }