Problem M. Walking Plan HDU - 6331

http://acm.hdu.edu.cn/showproblem.php?pid=6331

f[k][i][j]=min(f[k][i][j],f[k+1][i][j]) 这个式子是关键 通过该式子可以n^3的求出从i到j恰好走几步的最短距离

可以跑2e4次n^3 从后向前取最小值 即f[k][i][j]=min(f[k][i][j],f[k+1][i][j])

但是查询的k是1e4 还需要分块 就是把k分为k%100与k/100 前者只需要取恰好多少步的最短距离 后者取至少多少步的最短距离

至于为什么求至少多少步时需要多求很多次 因为两点之间的最短距离在最坏情况之下需要(n-1)次才可以求出 而在求出这个最优值之前 所有用此两点之间距离去松弛的操作都不会得到最优解

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 0x3f3f3f3f3f3f3f3f

ll e[60][60],fa[110][60][60],fb[210][60][60];
int n,m,q;

void getmul(ll a[][60],ll b[][60],ll c[][60])
{
    ll t[60][60];
    int i,j,k;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            t[i][j]=N;
            for(k=1;k<=n;k++)
            {
                t[i][j]=min(t[i][j],a[i][k]+b[k][j]);
            }
        }
    }
    memcpy(c,t,sizeof(t));
}

void solve()
{
    int i,j,k;
    memcpy(fb[1],e,sizeof(e));
    for(i=2;i<=200;i++)
    {
        getmul(e,fb[i-1],fb[i]);
    }
    memcpy(fa[1],fb[100],sizeof(e));
    for(i=2;i<=100;i++)
    {
        getmul(fb[100],fa[i-1],fa[i]);
    }
    for(k=199;k>=1;k--)
    {
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                fb[k][i][j]=min(fb[k][i][j],fb[k+1][i][j]);
            }
        }
    }
}

ll query(int u,int v,int a,int b)
{
    ll res;
    int i;
    res=N;
    for(i=1;i<=n;i++)
    {
        res=min(res,fa[a][u][i]+fb[b][i][v]);
    }
    return res;
}

int main()
{
    ll w,res;
    int t,i,j,u,v,k,a,b;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(e,0x3f,sizeof(e));
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%lld",&u,&v,&w);
            e[u][v]=min(e[u][v],w);
        }
        solve();
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d%d%d",&u,&v,&k);
            if(k<=100)
            {
                if(fb[k][u][v]==N) printf("-1\n");
                else printf("%lld\n",fb[k][u][v]);
            }
            else
            {
                a=(k-1)/100,b=k-100*a;
                res=query(u,v,a,b);
                if(res==N) printf("-1\n");
                else printf("%lld\n",res);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/81302804
今日推荐