题目传送门:https://www.luogu.org/problemnew/show/P1730
题意:
有n个点,m条边的有向图。现在有q个询问,每个询问求x~y的最小密度是多少。注意:最小密度=所经过路径的点劝和/路径数。
思路:
类似于floyd的dp。
f[i][j][l]表示从点i到j的路径经过l条路径的点权和最小的点权和。
则可知用一个k来枚举i~j的中转点,则f[i][j][l]=min(f[i][j][l],f[i][k][l-1]+f[k][j][1])即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,q;
int f[60][60][1010];
double ans;
int main()
{
int x,y,z;
scanf("%d %d",&n,&m);
memset(f,63,sizeof(f));
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
f[x][y][1]=min(f[x][y][1],z);
}
for(int l=2;l<=m;l++)
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j][l]=min(f[i][j][l],f[i][k][l-1]+f[k][j][1]);
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
ans=2147483647;
scanf("%d %d",&x,&y);
for(int l=1;l<=n;l++)
if(f[x][y][l]<106110956) ans=min(ans,(double)f[x][y][l]/l);
if(ans>=106110956) printf("OMG!\n"); else printf("%.3lf\n",ans);
}
}