bzoj1690:[Usaco2007 Dec]奶牛的旅行 (分数规划 && 二分 && spfa)

用dfs优化的spfa判环很快啦

分数规划的题目啦

二分寻找最优值,用spfa判断能不能使 Σ(mid * t - p) > 0

最优的情况只能有一个环

因为如果有两个环,两个环都可以作为奶牛的行程,如果两个环单独计算的结果不一样,那么两个环中比值更大的才是最优解,如果结果一样,多算一个环就没有意义了。

代码如下

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 using namespace std;
 5 const int N = 5010;
 6 
 7 int f[N], x, y;
 8 double mid;
 9 struct Edge{
10     int p, t;
11     double w;
12     inline void change() {
13         w = mid * (double)t - f[p];
14     }
15 };
16 vector < Edge > G[N];
17 bool vis[N];
18 double dis[N];
19 
20 bool spfa(const int &z){
21     vis[z] = true;
22     for(int i = 0; i < G[z].size(); i++)
23         if (dis[G[z][i].p] > dis[z] + G[z][i].w) {
24             if (vis[G[z][i].p])
25                 return true;
26             else {
27                 dis[G[z][i].p] = dis[z] + G[z][i].w;
28                 if (spfa(G[z][i].p))
29                     return true;
30             }
31         }
32     vis[z] = false;
33     return false;
34 }
35 
36 inline bool judge(){
37     for (int i = 1; i <= x; i++)
38         for (int j = 0; j < G[i].size(); j++)
39             G[i][j].change();
40     memset(vis, 0, sizeof(vis));
41     memset(dis, 0, sizeof(dis));
42     for (int i = 1; i <= x; i++)
43         if (spfa(i))
44             return true;
45     return false;
46 }
47 
48 int main() {
49     scanf("%d %d", &x, &y);
50     for (int i = 1; i <= x; i++)
51         scanf("%d", &f[i]);
52     for (int i = 1; i <= y; i++) {
53         int m, n, o;
54         scanf("%d %d %d", &m, &n, &o);
55         G[m].push_back((Edge) {n, o, 0});
56     }
57     double l = 0, r = 10000;
58     while (r - l > 0.000001) {
59         mid = (l + r) / 2;
60         if (judge())    l = mid;
61         else    r = mid;
62     }
63     printf("%.2lf", l);
64     return 0;
65 }

 

posted @ 2017-09-02 19:23  cminus  阅读(76)  评论(0编辑  收藏  举报