题意:
有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 协议 ,转载请注明出处!