最小密度路径
题目描述
给出一张有N个点M条边的加权有向无环图,接下来有Q个询问,每个询问包括2个节点X和Y,要求算出从X到Y的一条路径,使得密度最小(密度的定义为,路径上边的权值和除以边的数量)。
输入
第一行包括2个整数N和M。
以下M行,每行三个数字A、B、W,表示从A到B有一条权值为W的有向边。
再下一行有一个整数Q。
以下Q行,每行一个询问X和Y,如题意所诉。
输出
对于每个询问输出一行,表示该询问的最小密度路径的密度(保留3位小数),如果不存在这么一条路径输出“OMG!”(不含引号)。
样例输入
3 3 1 3 5 2 1 6 2 3 6 2 1 3 2 3
样例输出
5.000 5.500
提示
1 ≤ N ≤50,1 ≤ M ≤ 1000,1 ≤ W ≤ 10000,1 ≤ Q ≤100000
floyed,但要作修改;
f[i][j][k]表i到j有k条边的最小值。
这里已经很想dp了,但实际上已经差不多了。
f[i][j][l]=min(f[i][k][l-1]+f[k][j][1]);
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 int n,m; 7 long long f[51][51][51]; 8 double ans[51][51]; 9 int main() 10 {int a,b,w,i,j,k,l,q; 11 cin>>n>>m; 12 for (i=1;i<=50;i++) 13 for (j=1;j<=50;j++) 14 ans[i][j]=2e12; 15 for (i=1;i<=50;i++) 16 for (j=1;j<=50;j++) 17 for (l=1;l<=50;l++) 18 f[i][j][l]=2e12; 19 for (i=1;i<=m;i++) 20 { 21 scanf("%d%d%d",&a,&b,&w); 22 if (w<f[a][b][1]) 23 { 24 f[a][b][1]=w; 25 ans[a][b]=w; 26 } 27 } 28 for (l=2;l<=n;l++) 29 for (k=1;k<=n;k++) 30 for (i=1;i<=n;i++) 31 for (j=1;j<=n;j++) 32 { 33 if (f[i][k][l-1]+f[k][j][1]<f[i][j][l]) 34 f[i][j][l]=f[i][k][l-1]+f[k][j][1]; 35 if (f[i][j][l]!=2e12) 36 if ((double)f[i][j][l]/(double)l<ans[i][j]) 37 ans[i][j]=(double)f[i][j][l]/(double)l; 38 } 39 cin>>q; 40 for (i=1;i<=q;i++) 41 { 42 int x,y; 43 scanf("%d%d",&x,&y); 44 if (ans[x][y]!=2e12) 45 printf("%.3lf\n",ans[x][y]); 46 else printf("OMG!\n"); 47 } 48 }