• [APIO 2017] 商旅


    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=5367

    [算法]

             很明显的分数规划问题

             预处理从一个点走到另一个点所获最大利润和最短路

             SPFA判正环是否存在即可

             时间复杂度 : O(N ^ 2K + N ^ 2 logN)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    #define N 1010
    #define M 10010
    const double inf = 1e15;
    const double EPS = 1e-7;
    
    int n , m , k;
    int cnt[N];
    ll dist[N][N] , cst[N][N] , B[N][N] , S[N][N];
    double D[N][N] , dis[N];
    bool inq[N];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline bool check(double mid)
    {
            queue< int > q;
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= n; j++)
                    {
                            D[i][j] = 1.0 * cst[i][j] - 1.0 * dist[i][j] * mid;
                    }        
            }    
            memset(inq , false , sizeof(inq));
            for (int i = 1; i <= n; i++)
            {
                    q.push(i);
                    inq[i] = true;
                    cnt[i] = 1;
                    dis[i] = -inf;
            }  
            while (!q.empty())
            {
                    int cur = q.front();
                    q.pop();
                    inq[cur] = false;
                    for (int i = 1; i <= n; i++)
                    {
                            if (dis[cur] + D[cur][i] >= dis[i])
                            {
                                    dis[i] = dis[cur] + D[cur][i];
                                    if (!inq[i])
                                    {
                                            inq[i] = true;
                                            ++cnt[i];
                                            if (cnt[i] > n) return true;
                                            q.push(i);
                                    }
                            }
                    }
            }
            return false;
    }
    
    int main()
    {
            
            read(n); read(m); read(k);
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= 2 * k; j++)
                    {
                            ll x;
                            read(x);
                            if (j & 1) B[i][(j + 1) >> 1] = x;
                            else S[i][j >> 1] = x;
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= n; j++)
                    {
                            for (int x = 1; x <= k; x++)
                            {
                                    if (B[i][x] != -1 && S[j][x] != -1)
                                            chkmax(cst[i][j] , S[j][x] - B[i][x]);
                            }        
                    }        
            }
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= n; j++)
                    {
                            dist[i][j] = inf;
                    }
            }
            for (int i = 1; i <= m; i++)
            {
                    int u , v;
                    ll w;
                    read(u); read(v); read(w);
                    chkmin(dist[u][v] , w);
            }
            for (int x = 1; x <= n; x++)
            {
                    for (int i = 1; i <= n; i++)
                    {
                            for (int j = 1; j <= n; j++)
                            {
                                    chkmin(dist[i][j] , dist[i][x] + dist[x][j]);
                            }
                    }
            }
            double l = 0 , r = 0 , ans = 0;
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= n; j++)
                    {
                            chkmax(r , (double)cst[i][j]);        
                    }    
            } 
            while (r - l > EPS)
            {
                    double mid = (l + r) / 2.0;
                    if (check(mid))
                    {
                            l = mid;
                            ans = mid; 
                    } else r = mid;
            }
            printf("%lld
    " , (ll)ans);
            
            return 0;
        
    }
  • 相关阅读:
    (二)、一步一步学GTK+之窗口
    phpcms v9 评论的bug.
    为discuz x2.5添加播放附件(mp4)的方法
    code::blocks + C + lua 编译环境
    C语言从声卡录音的一个demo
    泛型集合(.NET 2.0)
    VS2008对ASP.NET引用的外部JS文件不能调试
    for循环和foreach
    CSS之DIV上下左右居中
    GridView控件相关(来自互联网)
  • 原文地址:https://www.cnblogs.com/evenbao/p/10427068.html
Copyright © 2020-2023  润新知