• 【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 }
  • 相关阅读:
    .Net 中double相加的困惑
    关于内存资源消耗快的问题
    内存资源消耗快的问题
    跨线程更新窗体
    .Net实现双缓冲
    TypeConverter
    emf文件的导入
    在资源中存放图象与emf文件的显示
    笔记java中nextLine方法没有输入就跳过了
    Silverlight Triggers、Actions 和 Behaviors
  • 原文地址:https://www.cnblogs.com/kane0526/p/2990163.html
Copyright © 2020-2023  润新知