题意:

有n个城市,每个城市有一个被抢劫的风险值,现在有q次询问,问u到v在不经过风险值大于w的条件下的最短路长度。其中

思路:

不经过某些城市就相当于不用某些城市松弛,这可以想到floyd,最外层是松弛的城市,所以容易想到要将城市的风险值进行从小到大排序,即从小到大进行松弛,再把每次松弛的结果保存下来,相当于三维dp表示经过前i个城市进行松弛j到k的最短路,这样预处理出来。

所以之后询问的时候遍历每个风险值,最后一个小于等于询问的风险值的就可以输出。

代码:

int n;
struct node
{
    int w;
    int id;
}a[210];
int dp[210][210][210];//通过前i个点松弛所得的最短路
bool cmp(node x,node y)
{
    return x.w<y.w;
}
int main()
{
    int t,q,x,y,z;
    scanf("%d",&t);
    for(int kase=1;kase<=t;kase++)
    {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].w);
            a[i].id=i;
        }
        sort(a+1,a+1+n,cmp);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&dp[i][j][0]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=n;k++)
                    dp[j][k][i]=min(dp[j][k][i-1],dp[j][a[i].id][i-1]+dp[a[i].id][k][i-1]);
        printf("Case #%d:\n",kase);
        while(q--)
        {
            scanf("%d%d%d",&x,&y,&z);
            if(a[n].w<=z){printf("%d\n",dp[x][y][n]);continue;}
            for(int i=1;i<=n;i++)
                if(a[i].w>z)
                {
                    printf("%d\n",dp[x][y][i-1]);
                    break;
                }
        }
    }
    return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

HDU3887 dfs序+树状数组 Previous
徐州邀请赛K 思维+最短路 Next