• 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

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

  • 相关阅读:
    oracle 11g如何完全卸载
    【Python】Django Model 怎么使用 UUID 作为主键?
    【云计算】K8S DaemonSet 每个node上都运行一个pod
    【Linux】为啥查某个进程的线程,查出来的所有线程的pid不一样啊
    【JavaScript】SVG vs Canvas vs WebGL
    【Python】使用 sphinx 制作简洁而又美观的文档
    【云计算】监控 告警 怎么做
    【Redis】Redis分布式集群几点说道
    【Hadoop】HIVE 小结概览
    【Hadoop】Hive HSQ 使用 && 自定义HQL函数
  • 原文地址:https://www.cnblogs.com/kedebug/p/3048247.html
Copyright © 2020-2023  润新知