码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 1733 分层网络流 ****

时间:2015-07-26 23:54:04      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:

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

链接:点我

 

A: 增加源点src,和汇点dest,然后根据每个时间点建出分层图,每个时间对应一层,对于每层图的构造如下

B:给每个格子标 上号Xi, 由于每个格子一次只能占一人,所以把每个格子分为两个点xa,xb,连上容量为1的有向边,对于格子为‘X’的,(如果为第0层的话)在源点src与xa 之间连一条容量为1的有向边,对于格子为‘@‘的点,在xb与汇点dest连上容量为1的有向边,对于每个格子,(除‘#’外),在xb与其上下左右及其本身 的对应下一层图的xa连上容量为1 的一条有向边

C:具体操作并不是一下子建出分层图,由于时间是未知的,所以枚举时间,做最大流,当最大流小于人数时,时间加一并在原图上增加一层,继续求最大流,直到最大流大于等于人数,这时的时间就是答案

 

原理懂了,代码也懂了,真自己敲估计还是很难敲出来,等专题训练吧

  1 /*HDU_1733 Escape*/
  2 /*分层图网络流+枚举时间*/
  3 /*AC代码:171ms*/
  4 #include <iostream>
  5 #include <cstdio>
  6 #include <memory.h>
  7 #include <algorithm>
  8 #define MAXN 20005
  9 #define Lim 75
 10 #define INF (1<<30)
 11 #define max(a,b) (a>b?a:b)
 12 #define min(a,b) (a<b?a:b)
 13 using namespace std;
 14 struct Node
 15 {
 16     int x,y;
 17     Node(int x1,int y1)
 18     {x=x1;y=y1;}
 19     Node(){}
 20 };
 21 struct edge
 22 {
 23     int u,v,w,next;
 24 }E[2000000];
 25 int head[MAXN],ecnt;
 26 int gap[MAXN],cur[MAXN],dis[MAXN],pre[MAXN];
 27 int N,M,scr,sink,vn,Ti,Sum,now;
 28 int ans;
 29 int dir[5][2]={0,1,0,-1,1,0,-1,0,0,0};
 30 char map[20][20];
 31 Node Q[200000];
 32 int Head,Tail;
 33 bool vis[20][20];
 34 void Insert(int u,int v,int w)
 35 {
 36     E[ecnt].u=u;
 37     E[ecnt].v=v;
 38     E[ecnt].w=w;
 39     E[ecnt].next=head[u];
 40     head[u]=ecnt++;
 41     E[ecnt].u=v;
 42     E[ecnt].v=u;
 43     E[ecnt].w=0;
 44     E[ecnt].next=head[v];
 45     head[v]=ecnt++;
 46 }
 47 bool BFS(Node s)
 48 {
 49     int i,j;
 50     Node u,v;
 51     memset(vis,false,sizeof(vis));
 52     Head=Tail=0;
 53     vis[s.x][s.y]=true;
 54     Q[Head++]=s;
 55     while(Head!=Tail)
 56     {
 57         u=Q[Tail++];
 58         if(map[u.x][u.y]==@) return true;
 59         for(i=0;i<4;i++)
 60         {
 61             int dx=u.x+dir[i][0];
 62             int dy=u.y+dir[i][1];
 63             if(dx>=0&&dx<N&&dy>=0&&dy<M&&map[dx][dy]!=#&&!vis[dx][dy])
 64             {
 65                 vis[dx][dy]=true;
 66                 Q[Head++]=Node(dx,dy);
 67             }
 68         }
 69     }
 70     return false;
 71 }
 72 bool OK()
 73 {
 74     bool ok=true;
 75     Node s;
 76     int i,j;
 77     for(i=0;i<N&&ok;i++)
 78     {
 79         for(j=0;j<M;j++)
 80         {
 81             if(map[i][j]==X)
 82             {
 83                 s.x=i;s.y=j;
 84                 if(!BFS(s))
 85                 {
 86                     ok=false;
 87                     break;
 88                 }
 89             }
 90         }
 91     }
 92     return ok;
 93 }
 94 void Init()
 95 {
 96     int i,j,u;
 97     memset(head,-1,sizeof(head));ecnt=0;
 98     for(i=0;i<N;i++)
 99         scanf("%s",map[i]);
100     scr=0;sink=1;vn=2;
101     Sum=0;
102     for(i=0;i<N;i++)
103     {
104         for(j=0;j<M;j++)
105         {
106             if(map[i][j]==X)
107             {
108                 Sum++;
109                 u=i*M+j+2;
110                 Insert(scr,u,1);
111             }
112         }
113     }
114     now=(M*N);
115     vn+=now;
116 }
117 int Sap(int s,int t,int n)//核心代码(模版)
118 {
119     int ans=0,aug=INF;//aug表示增广路的流量
120     int i,v,u=pre[s]=s;
121     for(i=0;i<=n;i++)
122     {
123         cur[i]=head[i];
124         dis[i]=gap[i]=0;
125     }
126     gap[s]=n;
127     bool flag;
128     while(dis[s]<n)
129     {
130         flag=false;
131         for(int &j=cur[u];j!=-1;j=E[j].next)//一定要定义成int &j,why
132         {
133             v=E[j].v;
134             if(E[j].w>0&&dis[u]==dis[v]+1)
135             {
136                 flag=true;//找到容许边
137                 aug=min(aug,E[j].w);
138                 pre[v]=u;
139                 u=v;
140                 if(u==t)
141                 {
142                     ans+=aug;
143                     while(u!=s)
144                     {
145                         u=pre[u];
146                         E[cur[u]].w-=aug;
147                         E[cur[u]^1].w+=aug;//注意
148                     }
149                     aug=INF;
150                 }
151                 break;//找到一条就退出
152             }
153         }
154         if(flag) continue;
155         int mindis=n;
156         for(i=head[u];i!=-1;i=E[i].next)
157         {
158             v=E[i].v;
159             if(E[i].w>0&&dis[v]<mindis)
160             {
161                 mindis=dis[v];
162                 cur[u]=i;
163             }
164         }
165         if((--gap[dis[u]])==0) break;
166         gap[dis[u]=mindis+1]++;
167         u=pre[u];
168     }
169     return ans;
170 }
171 
172 bool Judge(int Ti)
173 {
174     int i,j,k,u,v,a,b,dx,dy;
175     for(i=0;i<N;i++)
176     {
177         for(j=0;j<M;j++)
178         {
179             if(map[i][j]==#) continue;
180             u=i*M+j+1;
181             a=(Ti-1)*N*M;
182             b=a+N*M;
183             u=a+u+1;
184             for(k=0;k<5;k++)
185             {
186                 dx=i+dir[k][0];
187                 dy=j+dir[k][1];
188                 if(dx>=0&&dx<N&&dy>=0&&dy<M&&map[dx][dy]!=#)
189                 {
190                     v=dx*M+dy+1;
191                     v=b+v+1;
192                     Insert(u,v,1);
193                 }
194             }
195             if(map[i][j]==@)
196             {
197                 v=b+i*M+j+2;
198                 Insert(v,sink,1);
199             }
200         }
201     }
202     vn+=(N*M);
203     now+=(N*M);         //这个now好像没啥用
204     int t=Sap(scr,sink,vn);
205     ans+=t;
206     return ans==Sum;
207 }
208 void Solve()
209 {
210     if(Sum==0) {printf("0\n");return;}
211     if(!OK())  {printf("-1\n");return;}
212     ans=Ti=0;
213     while(true)
214     {
215         Ti++;
216         if(Judge(Ti)) break;
217     }
218     printf("%d\n",Ti);
219 }
220 int main()
221 {
222     while(scanf("%d%d",&N,&M)!=EOF)
223     {
224         Init();
225         Solve();
226     }
227 return 0;
228 }

 

hdu 1733 分层网络流 ****

标签:

原文地址:http://www.cnblogs.com/cnblogs321114287/p/4678891.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!