可以发现它的式子是一个分数规划的式子,所以可以二分答案,将所有边权减掉当前二分值之后跑一边$SPFA$判断负环即可。
然而这道题把$BFS-SPFA$卡掉了却没卡$DFS-SPFA$
出题人:想不到吧
然而这道题目其实是有结论的,具体可以去看rqy聚聚的blog,反正我是看不懂
// luogu-judger-enable-o2 #include<bits/stdc++.h> #define ld long double #define eps 1e-10 //This code is written by Itst using namespace std; inline int read(){ int a = 0; bool f = 0; char c = getchar(); while(c != EOF && !isdigit(c)){ if(c == '-') f = 1; c = getchar(); } while(c != EOF && isdigit(c)){ a = (a << 3) + (a << 1) + (c ^ '0'); c = getchar(); } return f ? -a : a; } const int MAXN = 3010 , MAXM = 10010; struct Edge{ int end , upEd; ld w; }Ed[MAXM]; ld minDis[MAXN]; int head[MAXN] , flo[MAXN] , N , M , cntEd; queue < int > q; bool inq[MAXN] , vis[MAXN]; inline void addEd(int a , int b , ld c){ Ed[++cntEd].end = b; Ed[cntEd].upEd = head[a]; head[a] = cntEd; Ed[cntEd].w = c; } /*bool SPFA(){ memset(minDis , 0 , sizeof(minDis)); for(int i = 1 ; i <= N ; ++i){ if(!inq[i]){ inq[i] = 1; q.push(i); } flo[i] = 1; } while(!q.empty()){ int t = q.front(); q.pop(); inq[t] = 0; for(int i = head[t] ; i ; i = Ed[i].upEd) if(minDis[Ed[i].end] > minDis[t] + Ed[i].w + eps){ minDis[Ed[i].end] = minDis[t] + Ed[i].w; flo[Ed[i].end] = flo[t] + 1; if(flo[Ed[i].end] > N) return 1; if(!inq[Ed[i].end]){ inq[Ed[i].end] = 1; q.push(Ed[i].end); } } } return 0; }*/ bool SPFA(int now){ vis[now] = 1; for(int i = head[now] ; i ; i = Ed[i].upEd) if(minDis[Ed[i].end] > minDis[now] + Ed[i].w) if(vis[Ed[i].end]) return 1; else{ minDis[Ed[i].end] = minDis[now] + Ed[i].w; if(SPFA(Ed[i].end)) return 1; } vis[now] = 0; return 0; } inline void add(ld num){ for(int i = 1 ; i <= cntEd ; ++i) Ed[i].w += num; } bool check(ld mid){ bool f = 0; add(-mid); memset(minDis , 0 , sizeof(minDis)); memset(vis , 0 , sizeof(vis)); for(int i = 1 ; !f && i <= N ; ++i) if(minDis[i] > -1e-8 && minDis[i] < 1e-8) f = SPFA(i); add(mid); return f; } int main(){ #ifndef ONLINE_JUDGE freopen("3199.in" , "r" , stdin); //freopen("3199.out" , "w" , stdout); #endif N = read(); M = read(); for(int i = 1 ; i <= M ; ++i){ int a = read() , b = read(); ld c; scanf("%Lf" , &c); addEd(a , b , c); } ld L = -1e7 , R = 1e7; while(R - L > eps){ ld mid = (L + R) / 2; check(mid) ? R = mid : L = mid; } printf("%.8Lf" , L); return 0; }