【HDU1733 Escape】 网络流

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1733

 

题目大意:有一个类似于迷宫搜索的图,‘.’代表的是无人的路,'X'代表有人的点,'#'代表此点不可通过,'@'代表门口。每个位置每一秒钟只能站一个人,每个位置到上下左右点的时间为1,问你所有人能不能出去,能出去输出所有人都出去的最小时间,否则输出-1.

 

解题思路:  第一次写这样的构造n层网络流的题,一开始完全没思路,纠结了良久。

          先用BFS判断所有人能不能出去,不能出去直接输出-1,不用构图了。二分枚举时间,选出所有人都能出去的最小时间。因为每点每时刻只能有一个人,所有对每个位置进行一次限流操作(先拆点,再限流)。因为我们是对时间进行操作,所以我们要构造mid层层次图(mid是二分枚举的时间,每层一秒),每个位置每一秒能往上下左右四个位置走,也能停留在原位置。

        这样构图,先拆点,拆成Xa点集合和Xb点集合,Xa->Xb对应点连1(限流操作),Xb向下一层的Xa对应位置以及上下左右位置连1(表示下一秒的流向),

每层Xb中的'@'都可以和超级汇点相连,只有第一层的‘X’才可以和超级源点相连。

View Code
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <queue>
  4 #include <algorithm>
  5 #include <cstring>
  6 using namespace std;
  7 
  8 const int mn=100024;
  9 const int mm=1000000;
 10 const int oo=0x3fffffff;
 11 int node, st, sd, edge;
 12 int reach[mm], flow[mm], next[mm];
 13 int head[mn], work[mn], que[mn], dis[mn];
 14 char map[20][20];
 15 int visit[20][20];
 16 int dir[4][2]= {1,0,-1,0,0,-1,0,1};
 17 int n, m;
 18 
 19 struct Node
 20 {
 21     int x, y;
 22 };
 23 
 24 bool BFS(int i, int j)
 25 {
 26     memset(visit,0,sizeof(visit));
 27     Node s, p;
 28     queue<Node>q;
 29     s.x=i, s.y=j;
 30     q.push(s);
 31     while(!q.empty())
 32     {
 33         p=q.front();
 34         q.pop();
 35         for(int k=0; k<4; k++)
 36         {
 37             s.x=p.x+dir[k][0];
 38             s.y=p.y+dir[k][1];
 39             if(s.x>=0&&s.x<n&&s.y>=0&&s.y<m&&map[s.x][s.y]!='#'&&!visit[s.x][s.y])
 40             {
 41                 visit[s.x][s.y]=1;
 42                 if(map[s.x][s.y]=='@') return true;
 43                 q.push(s);
 44             }
 45         }
 46     }
 47     return false;
 48 }
 49 
 50 void init(int _node, int _st, int _sd)
 51 {
 52     node=_node, st=_st, sd=_sd;
 53     for(int i=0; i<node; i++)
 54         head[i]=-1;
 55     edge=0;
 56 }
 57 
 58 inline void addedge(int u, int v, int c1, int c2)
 59 {
 60     reach[edge]=v, flow[edge]=c1, next[edge]=head[u],head[u]=edge++;
 61     reach[edge]=u, flow[edge]=c2, next[edge]=head[v],head[v]=edge++;
 62 }
 63 
 64 bool bfs()
 65 {
 66     int u, v, l=0, h=0;
 67     for(int i=0; i<node; i++) dis[i]=-1;
 68     que[l++]=st;
 69     dis[st]=0;
 70     while(l!=h)
 71     {
 72         u=que[h++];
 73         if(h==mn) h=0;
 74         for(int i=head[u]; i>=0; i=next[i])
 75         {
 76             v=reach[i];
 77             if(flow[i]&&dis[v]<0)
 78             {
 79                 dis[v]=dis[u]+1;
 80                 que[l++]=v;
 81                 if(l==mn) l=0;
 82                 if(v==sd) return true;
 83             }
 84         }
 85     }
 86     return false;
 87 }
 88 
 89 int dfs(int u, int exp)
 90 {
 91     if(u==sd) return exp;
 92     for(int &i=work[u]; i>=0; i=next[i])
 93     {
 94         int v=reach[i], tp;
 95         if(flow[i]&&dis[v]==dis[u]+1&&(tp=dfs(v,min(flow[i],exp))>0))
 96         {
 97             flow[i]-=tp;
 98             flow[i^1]+=tp;
 99             return tp;
100         }
101     }
102     return 0;
103 }
104 
105 int Dinic()
106 {
107     int  max_flow=0, flow;
108     while(bfs())
109     {
110         for(int i=0; i<node; i++) work[i]=head[i];
111         while(flow=dfs(st,oo)) max_flow+=flow;
112     }
113     return max_flow;
114 }
115 
116 void Makegraph(int mid)
117 {
118     init(mid*2*n*m+n*m+2,0,mid*2*n*m+n*m+1);
119     for(int k=0; k<mid; k++)
120     {
121         int tp=n*m, tm=2*n*m, cnt=k*2*n*m;
122         for(int i=0; i<n; i++)
123             for(int j=0; j<m; j++)
124             {
125                 if(map[i][j]!='#')
126                 {
127                     if(k==0&&map[i][j]=='X') addedge(st,cnt+i*m+j+1,1,0);
128                     addedge(cnt+i*m+j+1,cnt+tp+i*m+j+1,1,0);
129                     if(map[i][j]=='@') addedge(cnt+tp+i*m+j+1,sd,1,0);
130                     else
131                     {
132                         addedge(cnt+tp+i*m+j+1,cnt+tm+i*m+j+1,1,0);
133                         if(i!=0&&map[i-1][j]!='#')
134                             addedge(cnt+tp+i*m+j+1,cnt+tm+(i-1)*m+j+1,1,0);
135                         if(i!=n-1&&map[i+1][j]!='#')
136                             addedge(cnt+tp+i*m+j+1,cnt+tm+(i+1)*m+j+1,1,0);
137                         if(j!=0&&map[i][j-1]!='#')
138                             addedge(cnt+tp+i*m+j+1,cnt+tm+i*m+j,1,0);
139                         if(j!=m-1&&map[i][j+1]!='#')
140                             addedge(cnt+tp+i*m+j+1,cnt+tm+i*m+j+2,1,0);
141                     }
142                 }
143             }
144     }
145 }
146 
147 int main()
148 {
149     while(cin >> n >> m)
150     {
151         for(int i=0; i<n; i++)
152             scanf("%s",map[i]);
153         bool ok=true;
154         int num=0;
155         for(int i=0; i<n&&ok; i++)
156             for(int j=0; j<m&&ok; j++)
157             {
158                 if(map[i][j]=='X')
159                 {
160                     num++;
161                     if(!BFS(i,j)) ok=false;
162                 }
163             }
164         if(!ok) puts("-1");
165         else
166         {
167             int l=0, r=n*m, mid, ans=0;
168             while(l<=r)
169             {
170                 mid=(l+r)>>1;
171                 Makegraph(mid);
172                 if(Dinic()<num) l=mid+1;
173                 else
174                 {
175                     ans=mid-1;
176                     r=mid-1;
177                 }
178             }
179             cout << ans <<endl;
180         }
181     }
182     return 0;
183 }

 

posted @ 2013-03-30 11:13  Mr. Ant  阅读(553)  评论(0编辑  收藏  举报