zoukankan      html  css  js  c++  java
  • hdu6331 /// Floyd+分块DP

    题目大意:

    给定单向图的n m 为点数和单向边数

    接下来m行给定 u v w 为边的起点终点和长度

    给定q 为询问个数

    接下来q行给定 x y k 求从x到y至少经过k条边的最短路长度

    https://blog.csdn.net/qkoqhh/article/details/81301910

    设 d[ i ][ j ][ k ] 为从i到j走至少k条边的最短路长度

    设 f[ i ][ j ][ k ] 为从i到j恰好走k*100条边的最短路长度

    那么至少走K条边的话

    若 K>=100 有 f[ i ][ j ][ K/100 ] + d[ i ][ j ][ K%100 ]

    若 K%100==0 有 f[ i ][ j ][ K/100 ]

    若 K<100 有 d[ i ][ j ][ K ]

    最小值就是至少走K条边的最短路

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define INF 0x3f3f3f3f
    #define mem(i,j) memset(i,j,sizeof(i))
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int N=50+5;
    const int M=1e4+5;
    int n, m;
    int d[N][N][150], f[N][N][105];
    int main()
    {
        int _; scanf("%d",&_);
        while(_--) {
            scanf("%d%d",&n,&m);
            inc(i,1,n)inc(j,1,n) d[i][j][1]=INF; 
            while(m--) {
                int u,v,w; scanf("%d%d%d",&u,&v,&w);
                d[u][v][1]=min(d[u][v][1],w); // 更新至少1条边的答案
            }
            inc(i,1,n)inc(j,1,n) d[i][j][0]=d[i][j][1]; 
    // 至少0条边的答案应和至少1条相同
            inc(i,1,n) d[i][i][0]=0;
    // 点到本身的距离至少0条边答案肯定为0
            inc(k,2,150) {
                inc(i,1,n)inc(j,1,n) d[i][j][k]=INF;
                inc(p,1,n)inc(i,1,n)inc(j,1,n) // Floyd
                    d[i][j][k]=min(d[i][j][k],d[i][p][k-1]+d[p][j][1]);
            }
            inc(i,1,n)inc(j,1,n) f[i][j][1]=d[i][j][100];
    // 按100条边(求了150条)分块应该够了
            inc(k,2,100) {
                inc(i,1,n)inc(j,1,n) f[i][j][k]=INF;
                inc(p,1,n)inc(i,1,n)inc(j,1,n) // Floyd
                    f[i][j][k]=min(f[i][j][k],f[i][p][k-1]+f[p][j][1]);
            }
            dec(k,149,0)
                inc(i,1,n)inc(j,1,n)
                    d[i][j][k]=min(d[i][j][k],d[i][j][k+1]);
    // 至少k条边的答案 如果k+1的答案更优 同样可以更新
            int q; scanf("%d",&q);
            while(q--) {
                int u,v,k; scanf("%d%d%d",&u,&v,&k);
                int ans=INF;
                if(k>100) {
                    inc(p,1,n)
                    ans=min(ans,f[u][p][k/100]+d[p][v][k%100]);
                }
                if(k%100==0) ans=min(ans,f[u][v][k/100]);
                if(k<=100) ans=min(ans,d[u][v][k]);
                if(ans==INF) printf("-1
    ");
                else printf("%d
    ",ans);
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    python开源项目
    Appscan 10用户安装手册
    20201201-k8s的node节点和独立nginx部署会冲突
    k8s-更换证书(apiserver新添加了VIP)
    20201224-修改pod网段(calico)
    深-宝的一梦
    洛谷-P3383 【模板】线性筛素数
    洛谷-P3913 车的攻击
    洛谷-P1866 编号
    洛谷-P1100 高低位交换
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10416130.html
Copyright © 2011-2022 走看看