bzoj1486: [HNOI2009]最小圈 分数规划
题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=1486
题解
这题看了一个非常有意思的写法,有一个求有向图中最小平均权值回路的公式,证明见下http://www.cnblogs.com/y-clever/p/7043553.html。
\[ans=\min_{v\in V}\max_{0\leq k\leq n-1}\left[\cfrac{F_n(v)-F_k(v)}{n-k}\right]
\]
描述很清楚,看完按公式直接写就是了。(bz空间64mb,卡半天卡不过去,最后用float终于卡过去了!!YY太强辣%%
代码
#include<cstdio>
using namespace std;
const double INF=1e12;
const int maxn=3000+1;
const int maxm=1e4+1;
int n,m;
int u[maxm],v[maxm];
float w[maxm];
float f[maxn][maxn];
double min(double a,double b){return a<b?a:b;}
double max(double a,double b){return a>b?a:b;}
signed main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d%f",&u[i],&v[i],&w[i]);
for(int i=1;i<=n;i++) f[0][i]=0.0;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=INF;
for(int k=1;k<=n;k++) for(int i=1;i<=m;i++)
f[k][v[i]]=min(f[k][v[i]],f[k-1][u[i]]+w[i]);
double ans=1e7,res;
for(int i=1;i<=n;i++) if(f[n][i]<1e11){
double res=-INF;
for(int j=0;j<n;j++)
res=max(res,(f[n][i]-f[j][i])/(n-j));
ans=min(ans,res);
}
printf("%.8lf\n",ans);
return 0;
}