POJ3057:Evacuation——题解
http://poj.org/problem?id=3057
题目大意:
.为人,D为门,X为障碍,门每秒只能出去一个人,问多少秒出光。
如果无法出光输出impossible。
————————————————
首先bfs处理出来每个人到每个门的最短距离。
然后枚举时间,将时间与门作为二元组(或者理解为是make_pair也行)
当(当前时间)>=(该人到该门的时间),就把(这个人)与(这个门和当前时间的二元组)连起来。
然后二分图匹配找到匹配数比较和人数相不相等即可。
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int NUM1=101; const int NUM2=51; const int TP=NUM2*300; const int SUM=NUM1*TP; const int INF=2147483640; int dx[4]={0,-1,0,1}; int dy[4]={1,0,-1,0}; int cnt=0; int p[NUM1][TP]; struct pair{ int fi; int se; }turn[SUM]; int pii(int a,int b){ if(p[a][b])return p[a][b]; cnt++; turn[cnt].fi=a; turn[cnt].se=b; return p[a][b]=cnt; } int mp[15][15],dis[15][15],pos[15][15]; int to[NUM1][NUM2]; bool BFS(int xx,int yy,int r,int c){ for(int i=1;i<=r;i++){ for(int j=1;j<=c;j++){ dis[i][j]=INF; } } queue<int>q1,q2; q1.push(xx);q2.push(yy); dis[xx][yy]=0; bool ok=0; while(!q1.empty()){ int x=q1.front(),y=q2.front(); q1.pop();q2.pop(); if(mp[x][y]>0){ to[pos[xx][yy]][mp[x][y]]=dis[x][y]; ok=1; continue; } for(int i=0;i<4;i++){ int nx=x+dx[i],ny=y+dy[i]; if(nx>r||ny>c||nx<1||ny<1||mp[nx][ny]==-1)continue; if(dis[nx][ny]>dis[x][y]+1){ dis[nx][ny]=dis[x][y]+1; q1.push(nx);q2.push(ny); } } } return ok; } bool vis[TP],a[NUM1][TP]; int shu[TP]; bool dfs(int i){ for(int j=1;j<=cnt;j++){ if(a[i][j]&&!vis[j]){ vis[j]=1; if(!shu[j]||dfs(shu[j])){ shu[j]=i; return 1; } } } return 0; } int num1,num2; bool pan(int t){ memset(shu,0,sizeof(shu)); int ans=0; for(int i=1;i<=num1;i++){ memset(vis,0,sizeof(vis)); if(dfs(i))ans++; } if(ans!=num1)return 0; return 1; } void restart(){ cnt=0; num1=0; num2=0; memset(a,0,sizeof(a)); memset(p,0,sizeof(p)); memset(to,0,sizeof(to)); memset(mp,0,sizeof(mp)); memset(pos,0,sizeof(pos)); return; } int main(){ int N; cin>>N; while(N--){ restart(); int r,c; cin>>r>>c; for(int i=1;i<=r;i++){ for(int j=1;j<=c;j++){ char ch;cin>>ch; if(ch=='X')mp[i][j]=-1; else if(ch=='.'){ num1++; pos[i][j]=num1; }else mp[i][j]=1; } } for(int i=1;i<=r;i++){ for(int j=1;j<=c;j++){ if(mp[i][j]==1){ num2++; mp[i][j]=num2; } } } bool ha=0; for(int i=1;i<=r;i++){ for(int j=1;j<=c;j++){ if(!mp[i][j]){ if(!BFS(i,j,r,c)){ cout<<"impossible"<<endl; ha=1; break; } } } if(ha)break; } if(ha)continue; for(int i=1;;i++){ for(int j=1;j<=num1;j++){ for(int k=1;k<=num2;k++){ if(to[j][k]&&to[j][k]<=i){ a[j][pii(k,i)]=1; } } } if(pan(i)){ cout<<i<<endl; break; } } } return 0; }