动态规划训练之十八
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;
}