1. 程式人生 > >【二分答案】【最大流】[HNOI2007]緊急疏散EVACUATE

【二分答案】【最大流】[HNOI2007]緊急疏散EVACUATE

方向 會有 只有一個 bool ins long 輸入 上下 就是

[HNOI2007]緊急疏散EVACUATE

題目描述

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

輸入輸出格式

輸入格式:

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

輸出格式:

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

輸入輸出樣例

輸入樣例#1:
5 5
XXXXX
X...D
XX.XX
X..XX
XXDXX
輸出樣例#1:
3

試題分析:創建超級源S,超級匯T
     方便起見,先對於每一塊空地BFS求出它到每個能到達的門的距離

     然後二分答案,建圖。
     S連到每一個節點,容量為1的邊。代表每個位置上有一個人。
     簡單粗暴的建圖方法就是直接對於每個點將其每個時刻的點都建出來,會T一個點。
     考慮優化,發現我們不用管每個時刻這個門的狀態是什麽,而是只用關心最後從這個門出去多少個。
     所以我們的建圖方法如下:
     ①S連接到每一塊空地容量為1
     ②每一塊空地連接到其在二分答案時間內可以到的門,容量為1
     ③將每一個門連向T,容量為X(二分的時間)
     
代碼:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
inline int read(){
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}
#define LL long long
const int MAXN = 500001;
const int MAXN2 = 1000001;
const int INF = 9999999;

int N,M;
int Root[MAXN2+1],Next[MAXN2+1],Node[MAXN+1],C[MAXN2+1];
int cnt;
char Map[21][21];

void insert(int u,int v,int w){
    C[cnt]=w; Node[cnt]=v;
    Next[cnt]=Root[u]; Root[u]=cnt++;
    return ;
}
struct data{
    int x,y,tm;
}; 
bool vis[21][21];
int dis[21][21][21][21];
int dist[5][2]={{0,-1},{0,1},{1,0},{-1,0}};
int ans; int S,T,KT;
void BFST(){
    data t;
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
            if(Map[i][j]==‘.‘){
                ++KT;
                queue<data> Que;
                t.x=i; t.y=j; t.tm=0;
                Que.push(t);
                memset(vis,0,sizeof(vis)); vis[i][j]=true;
                while(!Que.empty()){
                    data k=Que.front(); Que.pop();
                    if(Map[k.x][k.y]==‘D‘){
                        dis[i][j][k.x][k.y]=k.tm;
                        continue;
                    }
                    for(int l=0;l<4;l++){
                        int xx=k.x+dist[l][0];
                        int yy=k.y+dist[l][1];
                        if(xx<1||yy<1||xx>N||yy>M||Map[xx][yy]==‘X‘||vis[xx][yy]) continue;
                        t.x=xx; t.y=yy; t.tm=k.tm+1;
                        vis[xx][yy]=true;
                        Que.push(t);
                    }
                }
            }
        }
    }
    return ;
}
int D[MAXN+1];
bool BFS(){
    queue<int> Que; Que.push(S);
    memset(D,0,sizeof(D)); D[S]=1;
    while(!Que.empty()){
        int k=Que.front(); Que.pop();
        for(int x=Root[k];x>-1;x=Next[x]){
            int v=Node[x];
            if(C[x]>0&&!D[v]){
                D[v]=D[k]+1;
                if(v==T) return true;
                Que.push(v);
            }
        }
    }
    return false;
}
int cur[MAXN+1];
int DFS(int k,int t){
    if(k==T) return t;
    int res=0;
    for(int x=cur[k];x>-1;x=Next[x]){
        int v=Node[x];
        if(C[x]>0&&D[v]==D[k]+1){
            int tmp=DFS(v,min(C[x],t));
            if(!tmp) continue;
            C[x]-=tmp; t-=tmp; C[x^1]+=tmp; res+=tmp;
            if(!t) return res;
        }
        cur[k]=x;
    }
    if(!res) D[k]=-1;
    return res;
}
bool check(int K){
    cnt=0;
    for(int i=0;i<=MAXN;i++) Root[i]=-1;
    memset(Next,0,sizeof(Next)); S=0,T=500000;
    memset(C,0,sizeof(C)); memset(Node,0,sizeof(Node));
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
            if(Map[i][j]==‘.‘){
                insert(S,(i-1)*M+j,1);
                insert((i-1)*M+j,S,0);
                for(int l1=1;l1<=N;l1++){
                    for(int l2=1;l2<=M;l2++){
                        if(Map[l1][l2]==‘D‘&&dis[i][j][l1][l2]&&dis[i][j][l1][l2]<=K){
                            insert((i-1)*M+j,(l1-1)*M+l2,1);
                            insert((l1-1)*M+l2,(i-1)*M+j,0);
                        }
                    }
                }
            }
            else if(Map[i][j]==‘D‘){
            	insert((i-1)*M+j,T,K); 
            	insert(T,(i-1)*M+j,0);
            }
        }
    }
    int ans=0; --cnt;
    while(BFS()){
    	for(int i=0;i<=N*M;i++) cur[i]=Root[i];
        ans+=DFS(S,INF);
    } 
    return ans>=KT;
}

int main(){
    N=read(),M=read();
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++)
            cin>>Map[i][j];
    }
    BFST();
    int l=0,r=400;
    while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    if(ans) printf("%d\n",ans);
    else puts("impossible");
}

  

 

【二分答案】【最大流】[HNOI2007]緊急疏散EVACUATE