[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\n" , (ll)ans);
        
        return 0;
    
}

 

posted @ 2019-02-24 17:59  evenbao  阅读(162)  评论(0编辑  收藏  举报