这里学了一个新知识叫分数规划
这道题目是求∑w[i]/S最小
首先二分答案k,然后
如果某个环∑w[i]/S<=k即
∑w[i]<=k*S-->∑w[i]-k*S<=0--->∑(w[i]-k)<=0
所以对于原图每条边变为w[i]-k,如果存在负圈,那么k还可以更小,否则反之
判负环可以用spfa,而这里由于我们只要找到一个负圈即可
所以我们用dfs类型的spfa而不用bfs型
这里有关于spfa的dfs和bfs比较
http://wenku.baidu.com/link?url=D8kKnPDyfVfUbp7FlkM6PV484bd_ikEPvZnHkgwquiqapU4rlbgxUzsF1M9ck3pu7sBpQlwrERWsMoyWTRE7PacJ_zsAPliqlt07wKY-olO
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 const eps=1e-9; 2 type node=record 3 po,next:longint; 4 len:extended; 5 end; 6 7 var w:array[0..20010] of node; 8 p:array[0..3010] of longint; 9 d:array[0..3010] of extended; 10 v:array[0..3010] of boolean; 11 x,y,n,m,i,len:longint; 12 z,l,r,mid:extended; 13 14 procedure add(x,y:longint;z:extended); 15 begin 16 inc(len); 17 w[len].po:=y; 18 w[len].len:=z; 19 w[len].next:=p[x]; 20 p[x]:=len; 21 end; 22 23 function dfs(x:longint):boolean; 24 var i,y:longint; 25 begin 26 v[x]:=true; 27 i:=p[x]; 28 while i<>0 do 29 begin 30 y:=w[i].po; 31 if d[y]>d[x]+w[i].len-mid then 32 begin 33 if not v[y] then 34 begin 35 d[y]:=d[x]+w[i].len-mid; 36 if dfs(y) then exit(true) 37 end 38 else exit(true); 39 end; 40 i:=w[i].next; 41 end; 42 v[x]:=false; 43 exit(false); 44 end; 45 46 function check:boolean; 47 var i:longint; 48 begin 49 for i:=1 to n do 50 d[i]:=0; 51 fillchar(v,sizeof(v),false); 52 for i:=1 to n do 53 if dfs(i) then exit(true); 54 exit(false); 55 end; 56 57 begin 58 readln(n,m); 59 l:=10000007; 60 r:=-10000007; 61 for i:=1 to m do 62 begin 63 readln(x,y,z); 64 add(x,y,z); 65 if z>r then r:=z; 66 if z<l then l:=z; 67 end; 68 while l+eps<r do 69 begin 70 mid:=(l+r)/2; 71 if check then r:=mid 72 else l:=mid; 73 end; 74 writeln(l:0:8); 75 end.