POJ 3057 Evacuation(二分图匹配+BFS)
【题目链接】 http://poj.org/problem?id=3057
【题目大意】
给出一个迷宫,D表示门,.表示人,X表示不可通行,
每个门每时间单位只允许一个人通过,
每个人移动一格的为一时间单位的时间,
问所有人逃离这个迷宫的最小时间
【题解】
我们首先对于每个门进行搜索,求出其到每个人的最短时间,
之后我们将每扇门对于人来拆点,分别为这个人第几秒通过这个门
将拆点后的门对所有人做一遍顺序二分图匹配
匹配最终完成的时间的门是其第几个拆点那么时间就是第几秒
【代码】
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <queue> using namespace std; const int MAX_V=10000; int V,match[MAX_V]; vector<int> G[MAX_V]; bool used[MAX_V]; void add_edge(int u,int v){ G[u].push_back(v); G[v].push_back(u); } bool dfs(int v){ used[v]=1; for(int i=0;i<G[v].size();i++){ int u=G[v][i],w=match[u]; if(w<0||!used[w]&&dfs(w)){ match[v]=u; match[u]=v; return 1; } }return 0; } const int dx[4]={-1,0,0,1},dy[4]={0,-1,1,0}; const int MAX_X=12,MAX_Y=12; int X,Y; char field[MAX_X][MAX_X+1]; vector<int> dX,dY; vector<int> pX,pY; int dist[MAX_X][MAX_Y][MAX_X][MAX_Y]; void bfs(int x,int y,int d[MAX_X][MAX_Y]){ queue<int> qx,qy; d[x][y]=0; qx.push(x); qy.push(y); while(!qx.empty()){ x=qx.front(); qx.pop(); y=qy.front(); qy.pop(); for(int k=0;k<4;k++){ int x2=x+dx[k],y2=y+dy[k]; if(0<=x2&&x2<X&&0<=y2&&y2<Y&&field[x2][y2]=='.'&&d[x2][y2]<0){ d[x2][y2]=d[x][y]+1; qx.push(x2); qy.push(y2); } } } } void solve(){ int n=X*Y; dX.clear(); dY.clear(); pX.clear(); pY.clear(); memset(dist,-1,sizeof(dist)); for(int x=0;x<X;x++){ for(int y=0;y<Y;y++){ if(field[x][y]=='D'){ dX.push_back(x); dY.push_back(y); bfs(x,y,dist[x][y]); }else if(field[x][y]=='.'){ pX.push_back(x); pY.push_back(y); } } } int d=dX.size(),p=pX.size(); for(int i=0;i<=n*d+p;i++)G[i].clear(); for(int i=0;i<d;i++){ for(int j=0;j<p;j++){ if(dist[dX[i]][dY[i]][pX[j]][pY[j]]>=0){ for(int k=dist[dX[i]][dY[i]][pX[j]][pY[j]];k<=n;k++){ add_edge((k-1)*d+i,n*d+j); } } } } if(p==0){ puts("0"); return; } int num=0; memset(match,-1,sizeof(match)); for(int v=0;v<n*d;v++){ memset(used,0,sizeof(used)); if(dfs(v)){ if(++num==p){ printf("%d\n",v/d+1); return; } } }puts("impossible"); } int T; void init(){ scanf("%d%d",&X,&Y); for(int i=0;i<X;i++)scanf("%s",field[i]); } int main(){ scanf("%d",&T); while(T--){ init(); solve(); }return 0; }
愿你出走半生,归来仍是少年