zoukankan      html  css  js  c++  java
  • [IndiaHacks 2016

    [IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2)] -D. Delivery Bears (二分+最大流)

    题面:

    题意:

    给定一个含有(mathit n)个节点(mathit m)个有向边的图和(mathit x)个工作小熊。保证有一个(1->n)的路径。

    现在让你选择一个最大的运输总值,满足当这(mathit x)个小熊均分任务后选择一些路径从(1->n),使其可以满足

    每一个有向边的容量不小于走过该边的小熊的任务总量。

    思路:

    显然可以在区间([1e(-6),1e6])这个区间去二分出每一个小熊最大的运输任务。

    对于check当前二分的数值(mid),我们需要用到网络流中的最大流算法,

    在原图的基础上将边权(c_i)改为(c_i/mid)向下取整的结果,跑最大流算法,得出(1->n)的最大流量(res)

    判断(res)(mathit x)的关系即可知道转移的方向。

    我才用ISAP算法求最大流:该算法的时间复杂度上限:(O(E*V^2)),理想情况:(O(sqrt(E)*V^2))

    于是本题的ac代码时间复杂度为(O(m*n^2*log_2x))

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000
    #define INF 1e15
    typedef long long ll;
    struct Edge {
        int from, to;
        ll cap, flow;
    };
    struct ISAP {
        int n, m, s, t;
        std::vector<Edge> edges;
        std::vector<int> G[N];
        bool vis[N];
        int d[N], cur[N];
        int p[N], num[N];
        void addedge(int from, int to, ll cap)
        {
            edges.push_back((Edge) {from, to, cap, 0});
            edges.push_back((Edge) {to, from, 0, cap});
            int m = edges.size();
            G[from].push_back(m - 2);
            G[to].push_back(m - 1);
        }
        void init()
        {
            memset(d, 0, sizeof(d));
            edges.clear();
            for (int i = 0; i <= n; ++i) {
                G[i].clear();
            }
        }
        ll Augument()
        {
            ll x = t, a = INF;
            while (x != s) {
                Edge &e = edges[p[x]];
                a = min(a, e.cap - e.flow);
                x = edges[p[x]].from;
            }
            x = t;
            while (x != s) {
                edges[p[x]].flow += a;
                edges[p[x] ^ 1].flow -= a;
                x = edges[p[x]].from;
            }
            return a;
        }
        void bfs()
        {
            memset(vis, 0, sizeof(vis));
            queue<int> q;
            q.push(t);
            d[t] = 0;
            vis[t] = 1;
            while (!q.empty()) {
                int x = q.front();
                q.pop();
                int len = G[x].size();
                for (int i = 0; i < len; ++i) {
                    Edge &e = edges[G[x][i]];
                    if (!vis[e.from] && e.cap > e.flow) {
                        vis[e.from] = 1;
                        d[e.from] = d[x] + 1;
                        q.push(e.from);
                    }
                }
            }
        }
        ll Maxflow(int s, int t)
        {
            this->s = s;
            this->t = t;
            ll flow = 0;
            bfs();
            memset(num, 0, sizeof(num));
            for (int i = 0; i < n; ++i) {
                num[d[i]]++;
            }
            int x = s;
            memset(cur, 0, sizeof(cur));
            while (d[s] < n) {
                if (x == t) {
                    flow += Augument();
                    x = s;
                }
                int ok = 0;
                for (int i = cur[x]; i < G[x].size(); ++i) {
                    Edge &e = edges[G[x][i]];
                    if (e.cap > e.flow && d[x] == d[e.to] + 1) {
                        ok = 1;
                        p[e.to] = G[x][i];
                        cur[x] = i;
                        x = e.to;
                        break;
                    }
                }
                if (!ok) {
                    int m = n - 1;
                    for (int i = 0; i < G[x].size(); ++i) {
                        Edge &e = edges[G[x][i]];
                        if (e.cap > e.flow) {
                            m = min(m, d[e.to]);
                        }
                    }
                    if (--num[d[x]] == 0) {
                        break;
                    }
                    num[d[x] = m + 1]++;
                    cur[x] = 0;
                    if (x != s) {
                        x = edges[p[x]].from;
                    }
                }
            }
            return flow;
        }
    } gao;
    
    int n;
    int m;
    int x;
    int a[N], b[N], c[N];
    
    bool check(double mid)
    {
        int S = 1;
        int T = n;
        gao.n = T + 1;
    
        for (int i = 1; i <= m; ++i) {
            ll num = floor(1.0 * c[i] / mid);
            gao.addedge(a[i], b[i], num);
        }
        int res = gao.Maxflow(S, T);
        gao.init();
        return res >= x;
    }
    int main()
    {
        scanf("%d %d %d", &n, &m, &x);
        for (int i = 1; i <= m; ++i) {
            scanf("%d %d %d", &a[i], &b[i], &c[i]);
        }
        double l = 1e-6;
        double r = 1000000;
        double ans, mid;
        for(int rp=1;rp<=100;++rp)
        {
            mid = (l + r) * 0.5;
            if (check(mid)) {
                l = mid;
                ans = mid;
            } else {
                r = mid;
            }
        }
        ans*=x;
        printf("%.6f
    ", ans );
        return 0;
    }
    
  • 相关阅读:
    python 端口扫描仪
    [ruby on rails] 深入(1) ROR的一次request的响应过程
    [ruby on rails] 跟我学之(10)数据输入验证
    [ruby on rails] 跟我学之(9)删除数据
    [ruby on rails] 跟我学之(8)修改数据
    [ruby on rails] 跟我学之(7)创建数据
    BZOJ 2301 [HAOI2011]Problem b (分块 + 莫比乌斯反演)
    BZOJ 2005 [Noi2010]能量采集 (数学+容斥 或 莫比乌斯反演)
    BZOJ 1497 [NOI2006]最大获利 (最小割)
    BZOJ [FJOI2007]轮状病毒 (找规律)
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/14193491.html
Copyright © 2011-2022 走看看