zoukankan      html  css  js  c++  java
  • POJ3228二分最大流

    题意:
          有n个点,每个点有两个权值,金子数量还有仓库容量,金子可以存在自己的仓库里或者是别的仓库里,仓库和仓库之间有距离,问所有金子都必须存到库里最大距离的最小是多少?


    思路:
          比较简单,方法也不唯一,大体可以这样,先二分,然后用最大流或者匹配..来判断是不是满足就行了,我用的是二分最大流,具体代码在下面。




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


    #define N_node 400 + 50
    #define N_edge 200 * 200 * 2 + 10000
    #define INF 1000000000


    using namespace std;


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


    typedef struct
    {
        int a ,b ,c;
    }EDGE;


    typedef struct
    {
        int x ,t;
    }DEP;


    STAR E[N_edge];
    EDGE edge[N_edge];
    DEP xin ,tou;
    int list[N_node] ,listt[N_node] ,tot;
    int deep[N_node];
    int c1[N_node] ,c2[N_node];
    int num[N_edge] ,numt[N_edge];




    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 = c;
        E[tot].next = list[b];
        list[b] = tot;
    }


    bool BFS_DEEP(int s ,int t ,int n)
    {
        memset(deep ,255 ,sizeof(deep));
        xin.x = s ,xin.t = 0;
        queue<DEP>q;
        q.push(xin);
        deep[s] = 0;
        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 minn(int x ,int y)
    {
        return x < y ? x : y;
    }


    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 c = E[k].cost ,to = E[k].to;
            if(!c || deep[to] != deep[s] + 1)
            continue;
            int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));
            nowflow += tmp;
            E[k].cost -= tmp;
            E[k^1].cost += tmp;
            if(nowflow == flow) 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;
    }


    int GetMaxFlow(int mid ,int n ,int m)
    {
        memset(list ,0 ,sizeof(list));
        tot = 1;
        for(int i = 1 ;i <= n ;i ++)
        {
            add(0 ,i ,c1[i]);
            add(i ,i + n ,INF);
            add(i + n ,n + n + 1 ,c2[i]);
        }


        for(int i = 1 ;i <= m ;i ++)
        {
            if(edge[i].c <= mid)
            {
                add(edge[i].a ,edge[i].b + n ,INF);
                add(edge[i].b ,edge[i].a + n ,INF);
            }
        }
        return DINIC(0 ,n + n + 1 ,n + n + 1);
    }


    int main ()
    {
        int n ,m ,i ,s1 ,s2;
        while(~scanf("%d" ,&n) && n)
        {
            s1 = s2 = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                scanf("%d" ,&c1[i]);
                s1 += c1[i];
            }
            for(i = 1 ;i <= n ;i ++)
            {
                scanf("%d" ,&c2[i]);
                s2 += c2[i];
            }
            scanf("%d" ,&m);
            for(i = 1 ;i <= m ;i ++)
            {
                scanf("%d %d %d" ,&edge[i].a ,&edge[i].b ,&edge[i].c);
                numt[i] = edge[i].c;
            }


            if(s2 < s1)
            {
                printf("No Solution ");
                continue;
            }


            sort(numt + 1 ,numt + m + 1);
            int numid = 0;
            for(i = 1 ;i <= m ;i ++)
            if(i == 1 || numt[i] != numt[i-1])
            num[++numid] = numt[i];
            num[0] = 0;
            int low = 0 ,up = numid ,mid ,ans = -1;
            while(low <= up)
            {
                mid = (low + up) >> 1;
                if(GetMaxFlow(num[mid] ,n ,m) == s1)
                {
                    ans = num[mid];
                    up = mid - 1;
                }
                else low = mid + 1;
            }
            if(ans == -1) printf("No Solution ");
            else printf("%d " ,ans);
        }
        return 0;
    }







  • 相关阅读:
    Wireshark抓包分析TCP 3次握手、4次挥手过程
    Wireshark基本介绍和学习TCP三次握手
    关于TCP窗口大小
    stat
    Disk
    内存对齐
    Openssl asn1parse命令
    checkinstall
    Nginx
    Linux top
  • 原文地址:https://www.cnblogs.com/csnd/p/12062458.html
Copyright © 2011-2022 走看看