hdu 1733 分层网络流 ****

题目大意:有一个类似于迷宫搜索的图,‘.’代表的是无人的路,'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)