这里学了一个新知识叫分数规划
这道题目是求∑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

 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.
View Code

 

posted on 2015-02-07 10:41  acphile  阅读(135)  评论(0编辑  收藏  举报