zoukankan      html  css  js  c++  java
  • [洛谷P1730] 最小密度路径

    类型:Floyd

    传送门:>Here<

    题意:定义一条路径密度 = 该路径长度 / 边数。给出一张$DAG$,现有$Q$次询问,每次给出$X,Y$,问$X,Y$的最小密度路径($N leq 50$)

    解题思路

    由于$N$非常小,考虑$Floyd$求最短路。但是这题与$Floyd$的不同就在于需要除以边数

    可以枚举边的数量。在边的数量$k$确定时,只需要求得恰好经过$k$条边的最短路即可。有没有联想到矩阵乘法……但是这道题是要求先预处理之后询问,因此矩阵乘法的$log M$优化就没有意义了,因为不管怎样$M$条边的最短路都要求出来

    $f[i][j][k]$表示路径$(i,j)$恰好经过$k$条边的最短路。于是我们易得$$f[i][j][k]=Min{ f[i][p][k-g]+f[p][j][g] }$$其中$p$枚举中介点,$g$枚举边数的中介点,$i,j,k$都要扫,于是复杂度$O(n^5)$……

    考虑省去一层循环。我们发现刚才的推法会有很多重复的情况,事实上既然已经枚举了中介点$p$,枚举$g$就没有意义了。我们就当$g=1$,因为$g eq 1$的情况一定会归属于$p$为其他节点时的情况。因此$$f[i][j][k]=Min{ f[i][p][k-1]+f[p][j][1] }$$

    Code

    会有重边,所以邻接矩阵赋值时要打最小值

    /*By DennyQi 2018.8.16*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    const int MAXN = 10010;
    const int MAXM = 27010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x<<3) + (x<<1) + c - '0', c = getchar();return x * w;
    }
    int N,M,Q,x,y,z;
    int f[55][55][1010];
    int main(){
        memset(f, 0x3f, sizeof(f));
        N=r,M=r;
        for(int i = 1; i <= M; ++i){
            x=r,y=r,z=r;
            f[x][y][1]=Min(f[x][y][1],z);
        }
        for(int g = 2; g <= M; ++g)
            for(int k = 1; k <= N; ++k)
                for(int i = 1; i <= N; ++i)
                    for(int j = 1; j <= N; ++j)
                        f[i][j][g] = Min(f[i][j][g], f[i][k][g-1] + f[k][j][1]);
        Q=r; 
        while(Q--){
            double cur,ans = 9999999.99; bool flg = 0;
            x=r, y=r;
            for(int k = 1; k <= M; ++k){
                if(f[x][y][k] != INF) flg = 1;
                cur = (double)f[x][y][k] / (double)k;
                ans = Min(ans, cur);
            }
            if(!flg){ printf("OMG!
    "); continue; }
            printf("%.3f
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    【Linux】Gitlab库已损坏前端显示500错误解决方法
    【linux】gitlab 的安装以及数据迁移
    【PHP】图片转换为base64,经过post传输后‘+’会变成 ‘空格’
    【Mac】解决外接显示器时无法用键盘调节音量
    【Mac】 /usr/local 文件夹权限问题
    学妹问的Spring Bean常用配置,我用最通俗易懂的讲解让她学会了
    上海月薪 1w 和家乡月薪 5000 你选择哪?
    30岁码农的一次面试经历:不委屈自己
    写4条宝贵的经验,给初入职场的你
    Java 8 Optional 良心指南,建议收藏
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9488734.html
Copyright © 2011-2022 走看看