1. 程式人生 > >緊急疏散evacuate

緊急疏散evacuate

memset 等於 esp tdi -h xxxxx 網絡流 最大 表示

1689: [HNOI2007]緊急疏散evacuate

題目描述

發生了火警,所有人員需要緊急疏散!假設每個房間是一個N M的矩形區域。每個格子如果是".",那麽表示這是一塊空地;如果是"X",那麽表示這是一面墻,如果是"D",那麽表示這是一扇門,人們可以從這兒撤出房間。已知門一定在房間的邊界上,並且邊界上不會有空地。最初,每塊空地上都有一個人,在疏散的時候,每一秒鐘每個人都可以向上下左右四個方向移動一格,當然他也可以站著不動。疏散開始後,每塊空地上就沒有人數限制了(也就是說每塊空地可以同時站無數個人)。但是,由於門很窄,每一秒鐘只能有一個人移動到門的位置,一旦移動到門的位置,就表示他已經安全撤離了。現在的問題是:如果希望所有的人安全撤離,最短需要多少時間?或者告知根本不可能。

輸入

輸入文件第一行是由空格隔開的一對正整數N與M,3<=N <=20,3<=M<=20,以下N行M列描述一個N M的矩陣。其中的元素可為字符"."、"X"和"D",且字符間無空格。

輸出

只有一個整數K,表示讓所有人安全撤離的最短時間,如果不可能撤離,那麽輸出"impossible"(不包括引號)。

樣例輸入

5 5  
XXXXX
X...D
XX.XX
X..XX
XXDXX

樣例輸出

3



  一道網絡流的題:我們發現時間是滿足單調性的,所以可以二分時間logn的復雜度,在當前時間限制下,將原點與每個人相連,每個人於能到達的不同時刻的每個門相連,意思是要將每個門拆點,拆成在不同時刻的門。所以要預處理出每個人到每個門的最短距離,跑一邊dfs,再由這些門與匯點相連,這些邊的容量為一;在這道題上炮最大流就行了,當且僅當最大流的數值等於總人數是,此時間點是可行的。
  如果最終結果為你二分的上界的話:意思是沒有這種情況,cout<<impossible;所以上界要定的稍大一些;


附代碼:
  
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<map>
  6 #include<queue>
  7 using namespace std;
  8 #define inf 5000000
  9 map<pair<int,int>,int>ma;
 10 int n,m,num,cnt,shu;
 11 int pos[21][21],id[21
][21],dis[401][401]; 12 char s[21][21];int adj[10002]; 13 struct flow{ 14 int s,t,w,next; 15 }k[2000001]; 16 int read(){ 17 int sum=0;char ch=getchar(); 18 while(ch<0||ch>9) ch=getchar(); 19 while(ch>=0&&ch<=9){sum=sum*10+ch-0;ch=getchar();} 20 return sum; 21 } 22 void dfs(int fa,int cnt,int x,int y){ 23 if(pos[x-1][y]==1){ 24 if(dis[fa][id[x-1][y]]>dis[fa][cnt]+1){ 25 dis[fa][id[x-1][y]]=dis[fa][cnt]+1; 26 dfs(fa,id[x-1][y],x-1,y); 27 } 28 } 29 if(pos[x+1][y]==1){ 30 if(dis[fa][id[x+1][y]]>dis[fa][cnt]+1){ 31 dis[fa][id[x+1][y]]=dis[fa][cnt]+1; 32 dfs(fa,id[x+1][y],x+1,y); 33 } 34 } 35 if(pos[x][y-1]==1){ 36 if(dis[fa][id[x][y-1]]>dis[fa][cnt]+1){ 37 dis[fa][id[x][y-1]]=dis[fa][cnt]+1; 38 dfs(fa,id[x][y-1],x,y-1); 39 } 40 } 41 if(pos[x][y+1]==1){ 42 if(dis[fa][id[x][y+1]]>dis[fa][cnt]+1){ 43 dis[fa][id[x][y+1]]=dis[fa][cnt]+1; 44 dfs(fa,id[x][y+1],x,y+1); 45 } 46 } 47 } 48 void search(int x,int y){ 49 dis[id[x][y]][id[x][y]]=0; 50 dfs(id[x][y],id[x][y],x,y); 51 } 52 void init(int s,int t,int w){ 53 k[num].s=s;k[num].t=t;k[num].w=w; 54 k[num].next=adj[s];adj[s]=num++; 55 } 56 void build(int lim){ 57 num=0;memset(adj,-1,sizeof(adj)); 58 for(int i=1;i<=n;++i) 59 for(int j=1;j<=m;++j){ 60 if(pos[i][j]==1) 61 init(0,id[i][j],1),init(id[i][j],0,0); 62 if(pos[i][j]==2){ 63 for(int u=1;u<=lim;++u) 64 init(ma[make_pair(id[i][j],u)],10000,1),init(10000,ma[make_pair(id[i][j],u)],0); 65 for(int u=1;u<=n;++u) 66 for(int p=1;p<=m;++p) 67 if(pos[u][p]==1) 68 for(int b=dis[id[i][j]][id[u][p]];b<=lim;++b) 69 init(id[u][p],ma[make_pair(id[i][j],b)],1),init(ma[make_pair(id[i][j],b)],id[u][p],0); } 70 } 71 } 72 int dp[10001]; 73 bool bfs(){ 74 memset(dp,0,sizeof(dp)); 75 queue<int>q; 76 q.push(0);dp[0]=1; 77 while(!q.empty()){ 78 int o=q.front();q.pop(); 79 for(int i=adj[o];i!=-1;i=k[i].next){ 80 if(!k[i].w||dp[k[i].t]) continue; 81 dp[k[i].t]=dp[o]+1; 82 if(k[i].t==10000) return true; 83 q.push(k[i].t); 84 } 85 } 86 return false; 87 } 88 int Dfs(int o,int fw){ 89 if(o==10000) return fw; 90 int tmp=fw,u; 91 for(int i=adj[o];i!=-1;i=k[i].next){ 92 if(!k[i].w||!tmp||dp[k[i].t]!=dp[o]+1) continue; 93 u=Dfs(k[i].t,min(k[i].w,tmp)); 94 if(!u){ 95 dp[k[i].t]=0;continue; 96 } 97 k[i].w-=u;k[i^1].w+=u;tmp-=u; 98 } 99 return fw-tmp; 100 } 101 bool judge(int ti){ 102 build(ti); 103 int ans=0; 104 while(bfs()) 105 ans+=Dfs(0,inf); 106 if(ans==shu) return true; 107 else return false; 108 } 109 int erfen(int l,int r){ 110 if(l==r) return l; 111 int mid=(l+r)>>1; 112 if(judge(mid)) 113 return erfen(l,mid); 114 else 115 return erfen(mid+1,r); 116 } 117 int main(){ 118 // freopen("a.in","r",stdin); 119 // freopen("a.out","w",stdout); 120 n=read();m=read(); 121 memset(adj,-1,sizeof(adj)); 122 memset(pos,0x3f,sizeof(pos)); 123 memset(dis,0x3f,sizeof(dis)); 124 for(int i=1;i<=n;++i) 125 scanf("%s",s[i]); 126 for(int i=1;i<=n;++i) 127 for(int j=1;j<=m;++j) 128 if(s[i][j-1]==D) 129 pos[i][j]=2,id[i][j]=++cnt; 130 else if(s[i][j-1]==.) 131 pos[i][j]=1,id[i][j]=++cnt,shu++; 132 cnt=n*m; 133 for(int i=1;i<=n;++i) 134 for(int j=1;j<=m;++j) 135 if(pos[i][j]==2) 136 for(int u=1;u<=200;++u) 137 ma[make_pair(id[i][j],u)]=++cnt; 138 for(int i=1;i<=n;++i) 139 for(int j=1;j<=m;++j) 140 if(pos[i][j]==2) 141 search(i,j); 142 int ans=erfen(0,200); 143 if(ans==200) printf("impossible"); 144 else printf("%d\n",ans); 145 return 0; 146 }


緊急疏散evacuate