• Luogu 2868 [USACO07DEC]观光奶牛Sightseeing Cows


    01分数规划复习。

    这东西有一个名字叫做最优比率环。

    首先这个答案具有单调性,我们考虑如何检验。

    设$frac{sum_{i = 1}^{n}F_i}{sum_{i = 1}^{n}T_i} = e$,我们需要检验的就是$sum_{i = 1}^{n}(F_i - mid * T_i) geq 0$是否存在。

    感觉这玩意不好算,再变形一下:$sum_{i = 1}^{n}(e * T_i - F_i) < 0$,就变成一个负环的检验了。

    $F_i$应当可以任取一条有向边的入点和出点。

    注意二分时的边界问题。

    时间复杂度$O(logn (spfa???))$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long double db;
    
    const int N = 1005;
    const int M = 5005;
    const db inf = 1e10;
    const db eps = 1e-6;
    
    int n, m, tot = 0, head[N];
    db dis[N], a[N];
    bool vis[N], ex;
    
    struct Edge {
        int to, nxt;
        db val;
    } e[M];
    
    inline void add(int from, int to, db val) {
        e[++tot].to = to;
        e[tot].val = val;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    template <typename T>
    inline void chkMax(T &x, T y) {
        if(y > x) x = y;
    }
    
    template <typename T>
    inline void chkMin(T &x, T y) {
        if(y < x) x = y;
    }
    
    void dfs(int x, db mid) {
        if(ex) return;
        vis[x] = 1;
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(dis[y] > dis[x] + mid * e[i].val - a[y]) {
                dis[y] = dis[x] + mid * e[i].val - a[y];
                if(vis[y]) {
                    ex = 1;
                    return;
                }
                dfs(y, mid);
            }
        }
        vis[x] = 0;
    }
    
    inline bool chk(db mid) {
        for(int i = 1; i <= n; i++) {
            dis[i] = 0.0;
            vis[i] = 0;
        }
        ex = 0;
        
        for(int i = 1; i <= n; i++) {
            dfs(i, mid);
            if(ex) break;
        }
        
        return ex;
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        db ln = 0.0, rn = 0.0, mid, res;
        for(int i = 1; i <= n; i++) scanf("%Lf", &a[i]);
        for(int i = 1; i <= m; i++) {
            int x, y; db v;
            scanf("%d%d%Lf", &x, &y, &v);
            add(x, y, v);
            rn += v;
        }
        
        for(; ln + eps <= rn; ) {
            mid = (ln + rn) * 0.5;
            if(chk(mid)) ln = mid, res = mid;
            else rn = mid;
        }
        
        printf("%.2Lf
    ", res);
        return 0;
    }
    View Code
  • 相关阅读:
    Python time
    Python List/Tutle/Set/Str/Dict
    python os
    Python 学习之九九乘法表
    Pycharm配置
    python 打包exe:
    Linux 安装PHP扩展过程
    tkinter在循环中创建按钮以传递命令参数,闭包的坑
    tkinter
    设置greenplum用户和密码访问:
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9872495.html
Copyright © 2020-2023  润新知