【题解】
最优比例路径,与最优比例环基本一致(最优比例环可参考uva11090 ,BZOJ1690)
用二分答案。假设答案为mid,只需要判断 从1到n是否存在平均值小于mid的最短路径。
假设一个包含k条边的最短路,最短路上各条边的权值为w1,w2……wk,那么平均值小于mid意味着 w1+w2+……wk< k+1* mid即:
(w1-mid)+(w2-mid)+……(wk-mid)-mid<0 (你会发现比最优比例环多了一个点,也就是多了一个mid,所以为了处理方便我们事先把0和起点添一条边权为0的边把起点设成0就行了)
换句话说,只要把图中每一条边a,b的权值w(a,b)变为w(a,b)-mid,在判断图中有没有总和为负值的最短路。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>
#include <queue>
#include <map>
using namespace std;
double a[1500],d[1500],l,r,mid,o;
struct info
{
int ar,next;
double l;
}road[10005];
int first[1500],i,j,k,m,num,n,sum,q[1500],f[1500],p1,q1;
void add(int x,int y,double len)
{
num++;
road[num].ar=y;road[num].next=first[x];
road[num].l=len;first[x]=num;
}
int spfa(double k,int z)
{
int i,h,t,u,v;
memset(f,0,sizeof(f));
for (i=1;i<=n;i++) d[i]=1e9;
t=1;h=0;q[1]=z;d[z]=0;f[z]=1;
for (;h!=t;)
{
h++;if (h==1500) h=0;u=q[h];f[u]=0;
for (i=first[u];i;i=road[i].next)
{
v=road[i].ar;
if (d[u]+road[i].l-a[v]*k<d[v])
{
d[v]=d[u]+road[i].l-a[v]*k;
if (!f[v])
{
t++;if (t==1500) t=0;
q[t]=v;f[v]=1;
}
}
}
}
return 0;
}
int pd(double k)
{
spfa(k,0);
if (d[n]<=0) return 1;
return 0;
}
int main()
{
scanf("%d%d",&n,&m);r=0;l=0;
add(0,1,0);
for (i=1;i<=n;i++) a[i]=1;
for (i=1;i<=m;i++)
{
scanf("%d%d%lf",&p1,&q1,&o);
add(p1,q1,o);
}
r=1e12;
for (;r-l>1e-5;)
{
mid=(l+r)/2;
if (pd(mid)) r=mid;else l=mid;
}
printf("%.3f\n",r);
}