[APIO2017]商旅

嘟嘟嘟

 

floyd + 01分数规划.

 

题中要求的是比率最大,那么自然就想到01分数规划。对于在哪几个城镇买卖商品,可以用O(n2 * k)贪心预处理。路程并不是两点间的距离,而是最短路,所以floyd先跑一遍。

因为答案下取整,所以整数二分就行。

此题卡dfs版spfa,只能用bfs版过……

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 using namespace std;
 12 #define enter puts("") 
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const ll INF = 1e14;
 19 const db eps = 1e-8;
 20 const int maxn = 105;
 21 inline ll read()
 22 {
 23   ll ans = 0;
 24   char ch = getchar(), last = ' ';
 25   while(!isdigit(ch)) {last = ch; ch = getchar();}
 26   while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
 27   if(last == '-') ans = -ans;
 28   return ans;
 29 }
 30 inline void write(ll x)
 31 {
 32   if(x < 0) x = -x, putchar('-');
 33   if(x >= 10) write(x / 10);
 34   putchar(x % 10 + '0');
 35 }
 36 
 37 int n, m, q;
 38 ll G[maxn][maxn], v[maxn][maxn], tra[maxn][maxn * 10][2];
 39 
 40 ll dis[maxn];
 41 bool vis[maxn];
 42 int cnt[maxn];
 43 /*bool spfa(int now, ll x)
 44 {
 45   vis[now] = 1;
 46   for(int i = 1; i <= n; ++i)
 47     {
 48       if(now != i && G[now][i] != INF && dis[i] >= dis[now] + x * G[now][i] - v[now][i])
 49     {
 50       dis[i] = dis[now] + x * G[now][i] - v[now][i];
 51       if(vis[i]) return 1;
 52       if(spfa(i, x)) return 1;
 53     }
 54     }
 55   vis[now] = 0;
 56   return 0;
 57 }*/
 58 
 59  bool spfa(ll x)
 60 {
 61   queue<int> q; q.push(0);
 62   while(!q.empty())
 63     {
 64       int now = q.front(); q.pop(); vis[now] = 0;
 65       for(int i = 1; i <= n; ++i)
 66     if(now != i && G[now][i] != INF && dis[i] >= dis[now] + x * G[now][i] - v[now][i])
 67       //一定是大于等于,因为可能有零环!
 68       {
 69         dis[i] = dis[now] + x * G[now][i] - v[now][i];
 70         if(!vis[i])
 71           {
 72         vis[i] = 1, q.push(i);
 73         if(++cnt[i] >= n) return 1;
 74           }
 75       }
 76     }
 77   return 0;
 78 }
 79 
 80 bool judge(ll x)
 81 {
 82   for(int i = 1; i <= n; ++i) dis[i] = INF;
 83   Mem(vis, 0); Mem(cnt, 0);
 84   dis[0] = 0;
 85   return spfa(x);
 86 }
 87 
 88 int main()
 89 {
 90   n = read(); m = read(); q = read();
 91   for(int i = 1; i <= n; ++i)
 92     for(int j = 1; j <= q; ++j) tra[i][j][0] = read(), tra[i][j][1] = read();
 93   for(int i = 1; i <= n; ++i)
 94     for(int j = 1; j <= n; ++j) G[i][j] = INF;
 95   for(int i = 1; i <= m; ++i)
 96     {
 97       int x = read(), y = read();
 98       ll w = read();
 99       G[x][y] = min(G[x][y], w);
100     }
101   for(int i = 1; i <= n; ++i) G[i][i] = 0;
102   for(int i = 1; i <= n; ++i)
103     for(int j = 1; j <= n; ++j)
104       {
105     for(int k = 1; k <= q; ++k)
106       if(tra[i][k][0] != -1 && tra[j][k][1] != -1)
107         v[i][j] = max(v[i][j], tra[j][k][1] - tra[i][k][0]);
108       }
109   for(int k = 1; k <= n; ++k)
110     for(int i = 1; i <= n; ++i)
111       for(int j = 1; j <= n; ++j)
112     G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
113   for(int i = 1; i <= n; ++i) G[0][i] = 0;
114   ll L = 0, R = 1e9;
115   while(L < R)
116     {
117       ll mid = (L + R + 1) >> 1;
118       if(judge(mid)) L = mid;
119       else R = mid - 1;
120     }
121   write(L), enter;
122   return 0;
123 }
View Code

 

posted @ 2018-10-26 14:16  mrclr  阅读(222)  评论(0编辑  收藏  举报