第一眼,卧槽这能做。。。
然后发现输出浮点数,不是要二分答案嘛。。。
于是就是二分答案,重构图然后判负圈。
判负圈的方法嘛,spfa即可。(大家这道题写的都是递归版的,于是蒟蒻也只敢写递归版的了T T)
结果跑到Rank1.上去了Oh耶!^_^
1 /************************************************************** 2 Problem: 1690 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:20 ms 7 Memory:920 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 14 using namespace std; 15 const int N = 1005; 16 const int M = 5005; 17 struct edges{ 18 int next, to, V; 19 double v; 20 }e[M]; 21 int n, m, tot, X, Y, Z; 22 int f[N], first[N]; 23 bool flag, v[N]; 24 double dis[N]; 25 26 inline int read(){ 27 int x = 0, sgn = 1; 28 char ch = getchar(); 29 while (ch < '0' || ch > '9'){ 30 if (ch == '-') sgn = -1; 31 ch = getchar(); 32 } 33 while (ch >= '0' && ch <= '9'){ 34 x = x * 10 + ch - '0'; 35 ch = getchar(); 36 } 37 return sgn * x; 38 } 39 40 void add_edge(int x, int y, int z){ 41 e[++tot].next = first[x], first[x] = tot; 42 e[tot].to = y, e[tot].V = z; 43 } 44 45 void build(double x){ 46 for (int i = 1; i <= tot; ++i) 47 e[i].v = e[i].V * x - f[e[i].to]; 48 } 49 50 void spfa(int p){ 51 v[p] = 1; 52 int x, y; 53 for (x = first[p]; x; x = e[x].next){ 54 y = e[x].to; 55 if (e[x].v + dis[p] < dis[y]){ 56 if (v[y]){ 57 flag = 1; 58 return; 59 } 60 dis[y] = e[x].v + dis[p]; 61 spfa(y); 62 } 63 } 64 v[p] = 0; 65 } 66 67 inline bool check(){ 68 memset(dis, 0, sizeof(dis)); 69 memset(v, 0, sizeof(v)); 70 flag = 0; 71 for (int i = 1; i <= n; ++i){ 72 spfa(i); 73 if (flag) return 1; 74 } 75 return 0; 76 } 77 78 int main(){ 79 n = read(), m = read(); 80 for (int i = 1; i <= n; ++i) 81 f[i] = read(); 82 for (int i = 1; i <= m; ++i){ 83 X = read(), Y = read(), Z = read(); 84 add_edge(X, Y, Z); 85 } 86 double l = 0, r = 10000, mid; 87 while (r - l > 0.001){ 88 mid = (l + r) / 2; 89 build(mid); 90 if (check()) l = mid; 91 else r = mid; 92 } 93 printf("%.2lf ", l); 94 return 0; 95 }