zoukankan      html  css  js  c++  java
  • HDU 1733 最大流

    题意:给一张n*m的图,#为墙壁,不可达,X为人,@为大门。问所有人到达大门的最短时间。

    在任意时间,每个点只能站一个人,大门一次也只能通过一个人。

    思路:枚举时间,每个时间建一次图,跑一次最大流,当最大流等于人数时,则该时间即为最短时间。

    关于建图,将每个点拆点。设置一个源点S,汇点T。当是点i是X时,S -> i ,流量为1 。

    任意时间ti。当点i不是#时,i + ti * n * m-> i' + ti * n * m ,流量是1。当点i是@时,i' +ti* n * m -> T ,流量是1。

    对于任意可达的两个点i ,j 连接 i -> j' + ti * n * m ,流量是1。

     另外,不可达情况可以对每个X进行BFS,若无法到达输出-1。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <string>
    #include <cmath>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <vector>
    #include <stack>
    #include <map>
    #include <iomanip>
    #define PI acos(-1.0)
    #define Max 50005
    #define inf 1<<28
    #define LL(x) (x<<1)
    #define RR(x) (x<<1|1)
    #define REP(i,s,t) for(int i=(s);i<=(t);++i)
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mp(a,b) make_pair(a,b)
    #define PII pair<int,int>
    #define xx first
    #define yy second
    using namespace std;
    inline void readint(int &ret)
    {
        char c;
        do
        {
            c = getchar();
        }
        while(c < '0' || c > '9');
        ret = c - '0';
        while((c=getchar()) >= '0' && c <= '9')
            ret = ret * 10 + ( c - '0' );
    }
    int n , m ;
    char Map[20][20] ;
    int peoplenum = 0 ;
    struct kdq
    {
        int s ,e ,l ,next ;
    } ed[Max * 100] ;
    int head[Max] , num ;
    int S , T ;
    int mx[5] = {0,1,-1,0,0} ;
    int my[5] = {0,0,0,1,-1} ;
    int deep[Max] ;
    int qe[Max * 100] ;
    int ans = 0 ;
    void add(int s ,int e ,int l )
    {
        ed[num].s = s ;
        ed[num].e = e ;
        ed[num].l = l ;
        ed[num].next = head[s] ;
        head[s] = num ++ ;
    
        ed[num].s = e ;
        ed[num].e = s ;
        ed[num].l = 0 ;
        ed[num].next = head[e] ;
        head[e] = num ++ ;
    }
    
    int inmap(int x ,int y )
    {
        if(x >= 0 && x < n && y >= 0 && y < m && Map[x][y] != '#')return 1 ;
        return 0 ;
    }
    bool bfs(PII s)//对每个X进行BFS,判断其是否可达大门@。
    {
        queue<PII>qe ;
        qe.push(s) ;
        bool vis[20][20] ;
        mem(vis,0) ;
        vis[s.xx][s.yy] = 1 ;
        while(!qe.empty())
        {
            PII tt = qe.front() ;
            qe.pop() ;
            if(Map[tt.xx][tt.yy] == '@')return 1 ;
            REP(i,0,4)
            {
                PII nextt ;
                nextt.xx = tt.xx + mx[i] ;
                nextt.yy = tt.yy + my[i] ;
                if(inmap(nextt.xx,nextt.yy) && !vis[nextt.xx][nextt.yy])
                {
                    vis[nextt.xx][nextt.yy] = 1 ;
                    qe.push(nextt) ;
                }
            }
        }
        return 0 ;
    }
    int dinic_bfs()
    {
        mem(deep,-1) ;
        deep[S] = 0 ;
        int h = 0 , t = 0 ;
        qe[h ++ ] = S ;
        while( h > t )
        {
            int tt = qe[ t ++ ] ;
            for (int i = head[tt] ; ~i ; i = ed[i].next )
            {
                int e = ed[i].e ;
                int l = ed[i].l ;
                if(l > 0 && deep[e] == -1)
                {
                    deep[e] = deep[tt] + 1 ;
                    qe[h ++ ] = e ;
                }
            }
        }
        return deep[T] != -1 ;
    }
    int dinic_dfs(int now ,int f)
    {
        if(now == T)return f ;
        int flow = 0 ;
        for (int i = head[now] ;~i ; i = ed[i].next )
        {
            int e = ed[i].e ;
            int l = ed[i].l ;
            if(deep[e] == deep[now] + 1 && l > 0 && (f - flow ) > 0 )
            {
                int mm = min(l,f - flow) ;
                int nn = dinic_dfs(e,mm) ;
                flow += nn ;
                ed[i].l -= nn ;
                ed[i ^ 1].l += nn ;
            }
        }
        if(flow == 0)deep[now] = -2 ;
        return flow ;
    }
    int dinic()
    {
        int flow = 0 ;
        while(dinic_bfs())
        {
            flow += dinic_dfs(S,inf) ;
        }
        return flow ;
    }
    bool check()
    {
        REP(i,0,n - 1)
        {
            REP(j,0,m - 1)
            {
                if(Map[i][j] == 'X')
                if(!bfs(mp(i,j)))return 0 ;
            }
        }
        return 1 ;
    }
    void build(int ceng)//对每个时间段进行建图。
    {
        REP(i,0,n - 1 )
            REP(j,0,m - 1)
            {
                if(Map[i][j] == '#')continue ;
                add(i * m + j + 1 + (ceng - 1) * n * m , i * m + j + 1 + n * m + (ceng - 1) * n * m , 1) ;//i + ti * n * m -> i' + ti * n * m 
                REP(k,0,4)
                {
                    int tx = i + mx[k] ;
                    int ty = j + my[k] ;
                    if(inmap(tx,ty))add(i * m + j + 1 + (ceng - 1) * n * m ,tx * m + ty + 1 + n * m + (ceng - 1) * n * m ,1) ;//两点可达, i + ti * n * m -> j' + ti * n * m 
                }
                if(Map[i][j] == '@')add(i * m + j + 1 + n * m + (ceng - 1) * n * m , T , 1) ;//若为大门 i' + ti * n * m-> T 
            }
    }
    
    int solve(int ceng)
    {
        build(ceng) ;
        ans += dinic() ;
        if(ans >= peoplenum)return 1 ;
        return 0 ;
    }
    void init()
    {
        mem(head,-1) ;
        num = 0 ;
        ans = 0 ;
        peoplenum = 0 ;
    }
    int main()
    {
        while(scanf("%d%d",&n,&m) != EOF)
        {
            init() ;
            S = 0 , T = 50000 ;
            REP(i,0,n - 1){
                scanf("%s",Map[i]) ;
                REP(j,0,m - 1)
                if(Map[i][j] == 'X'){
                    peoplenum ++ ;
                    add(S,i * m + j + 1 ,1) ;
                }
            }
            if(!peoplenum || !check())puts("-1") ;
            else
            {
                int ce = 1 ;
                while(1)
                {
                    if(solve(ce))break ;
                    ce ++ ;
                }
                printf("%d\n",ce) ;
            }
        }
        return 0;
    }
    


  • 相关阅读:
    shellshock溢出攻击
    内核编译与系统调用
    模块与系统调用
    20199315《Linux内核原理与分析》第十二周作业
    20199315《Linux内核原理与分析》第十一周作业
    Linux下的静态链接库和动态链接库
    2019-2020-1 20199315《Linux内核原理与分析》第九周作业
    2019-2020-1 20199315 《Linux内核原理与分析》 第八周作业
    2019-2020-1 20199315《Linux内核原理与分析》第七周作业
    2019-2020-1 20199315《Linux内核原理与分析》第六周作业
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3065732.html
Copyright © 2011-2022 走看看