bzoj 1189: [HNOI2007]紧急疏散evacuate

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #define inf 0x7fffffff
  5 #define M 5000008
  6 #define N 161000
  7 using namespace std;
  8 int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
  9 int map[21][21],n,m,D=1,a[410][22][22],q[1010][3],ans,cnt,head[N],next[M],u[M],v[M],T,tot,d1[N],q1[2*N];
 10 char ch[50];
 11 void zhao(int a1,int a2,int a3)
 12 {
 13     int h=0,t=1;
 14     q[1][0]=a2;
 15     q[1][1]=a3;
 16     q[1][2]=0;
 17     for(;h<t;)
 18       {
 19         h++;
 20         for(int i=0;i<4;i++)
 21           {
 22             int nx=q[h][0]+xx[i],ny=q[h][1]+yy[i];
 23             if(!nx||nx>n||!ny||ny>m||map[nx][ny]!=1)
 24               continue;
 25             if(a[a1][nx][ny]==inf)
 26               {
 27                 t++;
 28                 a[a1][nx][ny]=q[t][2]=q[h][2]+1;
 29                 q[t][0]=nx;
 30                 q[t][1]=ny;
 31               }
 32           }
 33       }
 34     return;
 35 }
 36 void jia(int a1,int a2,int a3)
 37 {
 38     cnt++;
 39     u[cnt]=a2;
 40     v[cnt]=a3;
 41     next[cnt]=head[a1];
 42     head[a1]=cnt;
 43     return;
 44 }
 45 bool bfs()
 46 {
 47     memset(d1,0,sizeof(int)*(T+1));
 48     int h=0,t=1;
 49     q1[1]=0;
 50     d1[0]=1;
 51     for(;h<t;)
 52       {
 53         h++;
 54         int p=q1[h];
 55         for(int i=head[p];i;i=next[i])
 56           if(!d1[u[i]]&&v[i])
 57             {
 58                 d1[u[i]]=d1[p]+1;
 59                 if(d1[T])
 60                   return 1;
 61                 t++;
 62                 q1[t]=u[i];
 63             }
 64       }
 65     return 0;
 66 }
 67 int dinic(int s,int f)
 68 {
 69     if(s==T)
 70       return f;
 71     int rest=f;
 72     for(int i=head[s];i&&rest;i=next[i])
 73       if(v[i]&&d1[u[i]]==d1[s]+1)
 74         {
 75             int now=dinic(u[i],min(rest,v[i]));
 76             if(!now)
 77               d1[u[i]]=0;
 78             v[i]-=now;
 79             v[i^1]+=now;
 80             rest-=now;
 81         }
 82     return f-rest;  
 83 }
 84 bool pan(int a1)
 85 {
 86     memset(head,0,sizeof(int)*(T+1));
 87     cnt=1;
 88     for(int i=1;i<=n;i++)
 89       for(int j=1;j<=m;j++)
 90         if(map[i][j]==1)
 91           {
 92             jia(0,(i-1)*m+j,1);
 93             jia((i-1)*m+j,0,0);
 94           }
 95     for(int k=2;k<=D;k++)
 96       for(int i=1;i<=n;i++)
 97         for(int j=1;j<=m;j++)
 98           if(a[k][i][j]!=inf)
 99            for(int l=1;l<=a1;l++)
100             if(a[k][i][j]<=l)
101               {
102                 jia((i-1)*m+j,n*m+D*(l-1)+k,1);
103                 jia(n*m+D*(l-1)+k,(i-1)*m+j,0);
104               }
105     for(int k=2;k<=D;k++)
106       for(int l=1;l<=a1;l++)
107       {
108         jia(n*m+D*(l-1)+k,T,1);
109         jia(T,n*m+D*(l-1)+k,0);
110       }
111     ans=0;
112     for(;bfs();)
113       ans+=dinic(0,inf);
114     if(ans==tot)
115       return 1;
116     return 0;
117 }
118 int main()
119 {
120     scanf("%d%d",&n,&m);
121     for(int i=1;i<=n;i++)
122       {
123         scanf("%s",ch+1);
124         for(int j=1;j<=m;j++)
125           {
126             if(ch[j]=='.')
127               {
128                 map[i][j]=1;
129                 tot++;
130               }
131             if(ch[j]=='D')
132               map[i][j]=++D;
133           }
134       }
135     T=160010;
136     for(int k=2;k<=D;k++)
137       for(int i=1;i<=n;i++)
138         for(int j=1;j<=m;j++)
139           a[k][i][j]=inf;
140     for(int i=1;i<=n;i++)
141       for(int j=1;j<=m;j++)
142         if(map[i][j]>1)
143           zhao(map[i][j],i,j);
144     int l=0,r=400,mn=-1;
145     for(;l<=r;)
146       {
147         int mid=(l+r)>>1;
148         if(pan(mid))
149           {
150             mn=mid;
151             r=mid-1;
152           }
153         else
154           l=mid+1;
155       }
156     if(mn==-1)
157       printf("impossible");
158     else
159       printf("%d\n",mn);
160     return 0;
161 }

网络流 先进行dfs 记入空地到每个门的时间 二分时间,建边判断是否满流,新加了数据,要对门按时间进行拆点

你可能感兴趣的:(bzoj 1189: [HNOI2007]紧急疏散evacuate)