https://www.luogu.org/problem/P2868
分析:
明显的01分数规划
求最优比率环
用dfs版的spfa找负环
二分就好
code by wzxbeliever:
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 51000 using namespace std; bool vis[N]; int n,m,x,y,z,tot; int c[N],num[N],head[N]; double ans,mid,l,r,w[N],dis[N]; struct Edge { int to,dis,from,next; }edge[N]; int add(int x,int y,int z) { tot++; edge[tot].to=y; edge[tot].dis=z; edge[tot].next=head[x]; head[x]=tot; } int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } int spfa(int x) { vis[x]=true; for(int i=head[x];i;i=edge[i].next) { int t=edge[i].to; if(dis[t]>dis[x]+w[i]) { dis[t]=dis[x]+w[i]; if(vis[t]||spfa(t)) { vis[x]=false; return true; } } } vis[x]=false; return false; } int pd() { for(int i=1;i<=n;i++)dis[i]=1e9; for(int i=1;i<=n;i++) if(spfa(i)) return true; return false; } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) c[i]=read(); for(int i=1;i<=m;i++) { x=read(),y=read(),z=read(); add(x,y,z); } l=0,r=500005; while(r-l>1e-6) { mid=(l+r)/2; for(int i=1;i<=tot;i++) { int t=edge[i].to; w[i]=(double)mid*edge[i].dis-c[t]; } if(pd())ans=mid,l=mid; else r=mid; } printf("%.2lf",ans); return 0; }