• Codeforces 653D Delivery Bears【二分+网络流】


    题目链接:

    http://codeforces.com/problemset/problem/653/D

    题意:

    x个熊拿着相同重量的物品,从1号结点沿着路走到N号结点,结点之间有边相连,保证可以从1号走到N号。

    The total weight that travels across a particular edge must not exceed the weight capacity of that edge.

    所有经过这条边的熊,他们所拿的重量之和不能大于这条边的容量。
    求所有熊所能拿的最大重量之和。

    分析:

    很明显的网络流。
    理解了题意便可以想到直接二分每个熊可以拿的重量,每边的容量代表经过熊的个数,这样在每次judge的时候对边进行处理,判断是否满流就好啦~~~

    代码:

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    using namespace std;
    typedef pair<int, int>pii;
    #define fi first
    #define se second
    struct edge{int to, cap, rev;};
    const int maxn = 10005, maxm = 20100, INF = 0x3f3f3f3f;
    int d[maxm], iter[maxm];
    int s, t;
    int x, m;
    int n, q;
    vector<edge>G[maxm];
    pii u[maxn];
    int a[maxn], b[maxn], c[maxn];
    void add_edge(int from, int to, int cap)
    {
        G[from].push_back((edge){to, cap, G[to].size()});
        G[to].push_back((edge){from, 0, G[from].size()-1});
    }
    void bfs()
    {
        memset(d, -1, sizeof(d));
        queue<int>q;
        d[s] = 0;
        q.push(s);
        while(!q.empty()){
            int v = q.front();q.pop();
            for(int i = 0; i <G[v].size(); i++){
                edge &e = G[v][i];
                if(e.cap>0&&d[e.to]<0){
                    d[e.to] = d[v] + 1;
                    q.push(e.to);
                }
            }
        }
    }
    int dfs(int v, int f)
    {
        if(v == t) return f;
        for(int &i = iter[v]; i < G[v].size(); i++){
            edge &e = G[v][i];
            if(e.cap > 0 && d[v] < d[e.to]){
                int tf = dfs(e.to, min(f, e.cap));
                if(tf > 0){
                    e.cap -= tf;
                    G[e.to][e.rev].cap +=tf;
                    return tf;
                }
            }
        }
        return 0;
    }
    int max_flow()
    {
        int flow = 0;
        for(;;){
            bfs();
            if(d[t]<0) return flow;
            memset(iter, 0, sizeof(iter));
            int f;
            while((f = dfs(s, INF))>0){
                flow += f;
            }
        }
    }
    bool judge(double mid)
    {
        for(int i = 0; i < maxn; i++)
            G[i].clear();
        for(int i = 0; i < m; i++){
            add_edge(a[i], b[i], min(1.0 * x, (double)c[i]/mid));//注意容量可能会爆int,所以取和x的最小值就好~
        }
        add_edge(n, t, x);
        add_edge(s, 1, x);
        return max_flow() == x;
    }
    int main (void)
    {
        scanf("%d%d%d",&n, &m, &x);
        for (int i = 0; i < m; i++){
             scanf("%d%d%d", &a[i], &b[i], &c[i]);
        }
        s = 0, t = n + 1;
        add_edge(n, t, INF);
        add_edge(s, 1, x);
    
        double l = 0, r = 1000005;
        for(int i = 0; i < 100; i++){
            double mid = (l + r)/2;
            if(judge(mid)) l  = mid;
            else r = mid;
        }
       printf("%.10f", l*x);
    }
    
    
  • 相关阅读:
    导出htmlcleaner
    备份
    本地win7搭建SVN
    nutch 导入ecl
    linux 启动nutch
    c++中的构造函数前加上explicit
    string::erase的使用心得
    C++的static关键字(转载)
    Boot Trigger
    strtol()详解
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758714.html
Copyright © 2020-2023  润新知