bzoj 1486 最小圈
分数规划,搜索参数P,把边权调整成val-p,然后找负环,如果存在负环说明答案可行并且还存在更优解,搜到精度满足即可。
minhoop
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #define maxn 10000 7 #define maxm 50000 8 using namespace std; 9 struct et 10 { 11 int s,t,next; 12 double val,cost; 13 }e[maxm]; 14 int v[maxn],fir[maxn]; 15 double dis[maxn]; 16 int n,m,tot; 17 18 bool find(int now) 19 { 20 v[now]=1; 21 for (int j=fir[now];j;j=e[j].next) 22 { 23 int k=e[j].t; 24 if (dis[now]+e[j].cost<dis[k]) 25 { 26 if (!v[k]) 27 { 28 dis[k]=dis[now]+e[j].cost; 29 if (find(k)) 30 { 31 v[now]=0; 32 return 1; 33 } 34 } 35 else 36 { 37 v[now]=0; 38 return 1; 39 } 40 } 41 } 42 v[now]=0; 43 return 0; 44 } 45 46 bool judge(double p) 47 { 48 for (int i=1;i<=tot;i++) e[i].cost=e[i].val-p; 49 for (int i=1;i<=n;i++) dis[i]=0; 50 for (int i=1;i<=n;i++) if (find(i)) return 1; 51 return 0; 52 } 53 54 void add(int x,int y,double z) 55 { 56 e[++tot].s=x; e[tot].t=y; e[tot].val=z; 57 e[tot].next=fir[x]; fir[x]=tot; 58 } 59 60 int main() 61 { 62 freopen("1486.in","r",stdin); 63 scanf("%d %d",&n,&m); 64 int x,y; 65 double z; 66 for (int i=1;i<=m;i++) 67 { 68 scanf("%d %d %lf",&x,&y,&z); 69 add(x,y,z); 70 } 71 double l=-1e7,r=1e7,ans=0; 72 while (l-r<=1e-9) 73 { 74 double mid=(l+r)/2; 75 //cout<<mid<<endl; 76 if (judge(mid)) r=mid-(1e-9),ans=mid; 77 else l=mid+(1e-9); 78 } 79 printf("%.8lf",ans); 80 return 0; 81 }
AC without art, no better than WA !