[bzoj1486]最小圈

分数规划。

用dfs判断一下是否有负圈。

然后二分。

其实这道题在lrj的白书上面有,“再谈BF算法”中讲过将求图上环平均值转换到二分的方法。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <queue>
 7 #include <string>
 8 #include <vector>
 9 #include <cmath>
10 using namespace std;
11 
12 const int N=20000;
13 int h[N],r[N],to[N],tot,n,m;
14 double w[N],ans;
15 void add(int u,int v,double c){
16     to[tot]=v;
17     r[tot]=h[u];
18     w[tot]=c;
19     h[u]=tot++;
20 }
21 
22 bool v[N],tmp;double d[N];
23 void dfs(int x,double mid){
24     v[x]=1;
25     for(int i=h[x];i!=-1;i=r[i]){
26         if(d[to[i]]>d[x]+w[i]-mid){
27             if(v[to[i]])return tmp=1,void();
28             d[to[i]]=d[x]+w[i]-mid;
29             dfs(to[i],mid);
30             if(tmp)return;
31         }
32     }
33     v[x]=0;
34 }
35 bool check(double mid){
36     memset(v,0,sizeof(v));
37     memset(d,0,sizeof(d));
38     tmp=0;
39     for(int i=1;i<=n;i++){dfs(i,mid);if(tmp)return 1;}
40     return 0;
41 }
42 
43 int main(){
44     memset(h,-1,sizeof(h));
45     scanf("%d%d",&n,&m);
46     for(int i=1;i<=m;i++){
47         int u,v;
48         double c;
49         scanf("%d%d%lf",&u,&v,&c);
50         add(u,v,c);
51     }
52     double l=-10000000,r=10000000;
53     while(r-l>0.0000000001){
54         double mid=(l+r)/2;
55         if(check(mid))ans=r=mid;
56         else l=mid;
57     }
58     printf("%.8lf\n",ans);
59 }
View Code

 

posted @ 2017-01-28 16:32  KingSann  阅读(205)  评论(0编辑  收藏  举报