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 }