zoukankan      html  css  js  c++  java
  • POJ 3621 Sightseeing Cows(SPFA + 构造负环)

    题意:

    牛可以从任意点出发, 每个点有欢乐值, 一个点可以去多次, 但是欢乐值只增加一次, 每条边有时间消耗, 求一条回路使得 总欢乐值/总时间 最大.

    思路:

    1. 对于有向边 (u, v) ,v 的权值可以表示成 d[u,v] * delta - fun[v],我们的目标是使 delta 尽量大

    2. 如果 delta 偏大,则可能图中不存在负环,这时要缩小 delta,如果 delta 偏小,存在负环,这时候增大 delta,继续 SPFA 判断

    3. 如 1->2->3->1 :

       (d[1,2]*delta-fun[2]) + (d[2,3]*delta-fun[3]) + (d[3,1]*delta-fun[1]) < 0

        => delta < (fun[1]+fun[2]+fun[3]) / (d[1,2]+d[2,3]+d[3,1])

    4. delta 其实就是最终我们要输出的结果。 

    #include <iostream>
    #include <queue>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 1010;
    const int INFS = 1e9;
    
    struct edge {
        int to, cost;
        edge(int _to, int _cost) : to(_to), cost(_cost) {}
    };
    
    int fun[MAXN], times[MAXN];
    double d[MAXN];
    bool inq[MAXN];
    vector<edge> G[MAXN];
    
    bool SPFA(int s, int n, double delta) {
        for (int i = 1; i <= n; i++) 
            times[i] = 0, d[i] = INFS, inq[i] = false;
        queue<int> Q;
        Q.push(s);
        times[s] = 1, inq[s] = true, d[s] = 0.0;
        while (!Q.empty()) {
            int u = Q.front(); Q.pop();
            inq[u] = false;
            for (int i = 0; i < G[u].size(); i++) {
                edge& e = G[u][i];
                if (d[e.to] > d[u] + delta*e.cost - fun[e.to]) {
                    d[e.to] = d[u] + delta*e.cost - fun[e.to];
                    if (!inq[e.to]) {
                        Q.push(e.to);
                        inq[e.to] = true;
                        times[e.to] += 1;
                        if (times[e.to] > n) return false;
                    }
                }
            }
        }
        return true;
    }
    
    int main() {
        int n, m;
        while (~scanf("%d%d", &n, &m)) {
            for (int i = 1; i <= n; i++) {
                scanf("%d", &fun[i]);
                G[i].clear();
            }
            for (int i = 0; i < m; i++) {
                int u, v, cost;
                scanf("%d%d%d", &u, &v, &cost);
                G[u].push_back(edge(v, cost));
            }
            int l = 0, r = 10000000;
            while (l <= r) {
                int mid = (l + r) / 2;
                if (SPFA(1, n, mid*1.0/1000))
                    r = mid - 1;
                else 
                    l = mid + 1;
            }
            if (r % 10 > 4)
                r = (r/10+1) * 10;
            else 
                r = (r/10) * 10;
            printf("%.2lf\n", r*1.0/1000);
        }
        return 0;
    }
    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    导出htmlcleaner
    备份
    本地win7搭建SVN
    nutch 导入ecl
    linux 启动nutch
    c++中的构造函数前加上explicit
    string::erase的使用心得
    C++的static关键字(转载)
    Boot Trigger
    strtol()详解
  • 原文地址:https://www.cnblogs.com/kedebug/p/3048247.html
Copyright © 2011-2022 走看看