zoukankan      html  css  js  c++  java
  • POJ2391 Floyd+离散化+二分+DINIC

    题意:
          有n个猪圈,每个猪圈里面都有一定数量的猪(可能大于当前猪圈的数量),每个猪圈都有自己的容量,猪圈与猪圈之间给出了距离,然后突然下雨了,问多久之后所有的猪都能进圈。


    思路:
           先跑一遍Floyd求出任意两点之间的最短距离,对于时间,也就是答案,我们可以二分去找,然后对于每次二分,我们可以用DINIC去判断是否满足要求,建图的时候记得拆点,一开始我感觉不用抄点,但是都敲完了,发现不行,又重新建图了,拆成二分图,然后根据当前二分的值连边。。。这个题比较简单,没啥难点,就是长时间没写了,练练手,还有提醒一点,二分的时候可以不直接二分时间,我们可以吧所有可能的时间都找出来,排序,离散化一下,这样直接二分下标,减少时间开销(直接不离散化目测也行,但是离散化能更快点)。下面是我的代码,用的方法是 Floyd+离散化+二分+DINIC做的,这个题思路不难,就是练练手,就解释这么多。
          


    #include<queue>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>


    #define N_node 400 + 10
    #define N_edge (200 * 200 + 400) * 2 + 100
    #define INF 2000000000
    #define III 0x3f3f3f3f3f3f3f3f




    using namespace std;


    typedef struct
    {
        int to ,cost ,next;
    }STAR;


    typedef struct
    {
        int x ,t;
    }DEP;


    DEP xin ,tou;
    STAR E[N_edge];
    int list[N_node] ,listt[N_node] ,tot;
    int deep[N_node];
    long long map[202][202];
    long long tmp[50000] ,num[50000];
    int L[202] ,R[202];
    int S;


    void add(int a ,int b ,int c)
    {
        E[++tot].to = b;
        E[tot].cost = c;
        E[tot].next = list[a];
        list[a] = tot;


        E[++tot].to = a;
        E[tot].cost = 0;
        E[tot].next = list[b];
        list[b] = tot;
    }


    int minn(int x ,int y)
    {
        return x < y ? x : y;
    }


    void Floyd(int n)
    {
        for(int k = 1 ;k <= n ;k ++)
        for(int i = 1 ;i <= n ;i ++)
        for(int j = 1 ;j <= n ;j ++)
        if(map[i][j] > map[i][k] + map[k][j])
        map[i][j] = map[i][k] + map[k][j];
    }


    bool BFS_Deep(int s ,int t ,int n)
    {
        memset(deep ,255 ,sizeof(deep));
        deep[s] = 0;
        xin.x = s ,xin.t = 0;
        queue<DEP>q;
        q.push(xin);
        while(!q.empty())
        {
            tou = q.front();
            q.pop();
            for(int k = list[tou.x] ;k ;k = E[k].next)
            {
                xin.x = E[k].to;
                xin.t = tou.t + 1;
                if(deep[xin.x] != -1 || !E[k].cost)
                continue;
                deep[xin.x] = xin.t;
                q.push(xin);
            }
        }
        for(int i = 0 ;i <= n ;i ++)
        listt[i] = list[i];
        return deep[t] != -1;
    }


    int DFS_Flow(int s ,int t ,int flow)
    {
        if(s == t) return flow;
        int nowflow = 0;
        for(int k = listt[s] ;k ;k = E[k].next)
        {
            listt[s] = k;
            int to = E[k].to;
            int c = E[k].cost;
            if(deep[to] != deep[s] + 1 || !c)
            continue;
            int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));
            nowflow += tmp;
            E[k].cost -= tmp;
            E[k^1].cost += tmp;
            if(flow == nowflow) break;
        }
        if(!nowflow) deep[s] = 0;
        return nowflow;
    }


    int DINIC(int s ,int t ,int n)
    {
        int Ans = 0;
        while(BFS_Deep(s ,t ,n))
        {
            Ans += DFS_Flow(s ,t ,INF);
        }
        return Ans;
    }


    void Buid(int n ,long long mid)
    {
        memset(list ,0 ,sizeof(list)) ,tot = 1;
        for(int i = 1 ;i <= n ;i ++)
        add(0 ,i ,L[i]) ,add(i + n ,n + n + 1 ,R[i]);
        for(int i = 1 ;i <= n ;i ++)
        for(int j = 1 ;j <= n ;j ++)
        if(map[i][j] <= mid) add(i ,j + n ,INF);
    }


    long long solve(int n)
    {
        int t = 0;
        for(int i = 1 ;i <= n ;i ++)
        for(int j = i ;j <= n ;j ++)
        if(map[i][j] != III) tmp[++t] = map[i][j];
        sort(tmp + 1 ,tmp + t + 1);
        int numn = 0;
        for(int i = 1 ;i <= t ;i ++)
        if(i == 1 || tmp[i] != tmp[i-1])
        num[++numn] = tmp[i];
        int low = 1 ,up = numn ,mid;
        long long Ans = -1;
        while(low <= up)
        {
            mid = (low + up) >> 1;
            Buid(n ,num[mid]);
            if(DINIC(0 ,n + n + 1 ,n + n + 1) == S)
            {
                Ans = num[mid];
                up = mid - 1;
            }else low = mid + 1;
        }
        return Ans;
    }


    int main ()
    {
        int n ,m ,i ,j;
        long long a ,b ,c;
        while(~scanf("%d %d" ,&n ,&m))
        {
            for(S = 0 ,i = 1 ;i <= n ;i ++)
            {
                scanf("%d %d" ,&L[i] ,&R[i]);
                S += L[i];
            }
            for(i = 1 ;i <= n ;i ++)
            {
                for(j = i + 1;j <= n ;j ++)
                map[i][j] = map[j][i] = III;
                map[i][i] = 0;
            }


            for(i = 1 ;i <= m ;i ++)
            {
                scanf("%lld %lld %lld" ,&a ,&b ,&c);
                if(map[a][b] > c) map[a][b] = map[b][a] = c;
            }
            Floyd(n);
            long long Ans = solve(n);
            printf("%lld " ,Ans);
        }
        return 0;
    }





  • 相关阅读:
    SQL Server将一列的多行内容拼接成一行的问题讨论
    SQL 获取 IDENTITY 三种方法 SCOPE_IDENTITY、IDENT_CURRENT 和 @@IDENTITY的区别
    构建高性能服务(二)
    乐观锁解决高并发
    c#问答篇:对象与引用变量-----初学者的困惑
    vs调试 本地IIS
    【转】android adb常用指令
    【转】使用 JMeter 完成常用的压力测试
    【转】利用 Apache JMeter 测试 WebSphere 性能
    【转】用JMeter来测试Tomcat的性能
  • 原文地址:https://www.cnblogs.com/csnd/p/12062471.html
Copyright © 2011-2022 走看看