【NOIP2016模拟赛No.1】 最小密度路径

本文介绍了一个关于求解加权有向无环图中两点间最小密度路径的问题,并提供了解决方案。通过增加一个维度来表示经过的边数,利用floyd算法计算最短路径,最终得出每个询问的最小密度路径。

题目描述

这次的任务很简单,给出了一张有N 个点M 条边的加权有向无环图,接下来有Q 个询问,每个询问包括2 个节点X Y ,要求算出从X Y 的一条路径,使得密度最小(密度的定义为,路径上边的权值和除以边的数量)。

输入

第一行包括2 个整数N M 

以下M 行,每行三个数字ABW ,表示从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 

提示

对于60% 的数据,有1N10 1M100 1W1000 1Q1000 

对于100% 的数据,有1N50 1M1000 1W100000 1Q100000 

题解
有一句经典的话:如果状态有后效性,就加一维使它没有后效性。

看到上面那句话应该就可以懂怎么做了……如果不懂,看下一句……

加一维表示经过的边数,跑最短路……

spfa floyd ,什么什么的随便乱跑跑就好
f[i][j][k] 表示从i j 经过k 条边的最短路

代码

#include<stdio.h>
#include<cstring>
#define N 55
#define For(i,a,b) for (int i=a;i<=b;i++)

int n,m,q,u,v,f[N][N][N],c[N][N],p;

inline void floyd()
{
    For(i,1,n) f[i][i][0]=0;
    For(s,1,n) For(k,1,n) For(i,1,n) For(j,1,n) if (f[i][j][s]>f[i][k][s-1]+c[k][j])
    f[i][j][s]=f[i][k][s-1]+c[k][j];
}

int main()
{
    scanf("%d%d",&n,&m);
    memset(c,0x3f,sizeof(c));
    memset(f,0x3f,sizeof(f));
    int inf=c[0][0];
    while (m--)
    {
        scanf("%d%d%d",&u,&v,&p);
        if (p<c[u][v]) c[u][v]=p;
    }
    floyd();
    scanf("%d",&q);
    while (q--)
    {
        scanf("%d%d",&u,&v);
        double ans=18915758;
        bool flag=0;
        For(i,0,n) if (f[u][v][i]<inf)
        {
            flag=1;
            if (ans*i>f[u][v][i]) ans=(double)f[u][v][i]/i;
        }
        if (flag) printf("%.3lf\n",ans);
        else puts("OMG!");
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值