最小密度路径

题目描述

给出一张有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 }

 

posted @ 2017-06-20 21:47  Z-Y-Y-S  阅读(362)  评论(0编辑  收藏  举报