计蒜客暑假集训第一阶段第4场 f题

Firdaws and Fatinah are living in a country with nn cities, numbered from 11 to nn.Each city has a risk of kidnapping or robbery.

Firdaws's home locates in the city uu, and Fatinah's home locates in the city vv.Now you are asked to find the shortest path from the city uu to the city vv that does not pass through any other city with the risk of kidnapping or robbery higher than ww, a threshold given by Firdaws.

Input Format

The input contains several test cases, and the first line is a positive integer TT indicating the number of test cases which is up to 5050.

For each test case, the first line contains two integers n~(1\le n\le 200)n (1≤n≤200) which is the number of cities, and q~(1\le q\le 2\times 10^4)q (1≤q≤2×104) which is the number of queries that will be given.The second line contains nn integers r_1, r_2, \cdots, r_nr1​,r2​,⋯,rn​ indicating the risk of kidnapping or robbery in the city 11 to nn respectively.Each of the following nnlines contains nn integers, the jj-th one in the ii-th line of which, denoted by d_{i,j}di,j​, is the distance from the city ii to the city jj.

Each of the following qq lines gives an independent query with three integers u, vu,v and ww, which are described as above.

We guarantee that 1\le r_i \le 10^51≤ri​≤105, 1\le d_{i,j}\le 10^5~(i \neq j)1≤di,j​≤105 (i≠j), d_{i,i}=0di,i​=0 and d_{i,j}=d_{j,i}di,j​=dj,i​.Besides, each query satisfies 1\le u,v\le n1≤u,v≤n and 1\le w\le 10^51≤w≤105.

Output Format

For each test case, output a line containing Case #x: at first, where xx is the test case number starting from 11.Each of the following qq lines contains an integer indicating the length of the shortest path of the corresponding query.

样例输入

1
3 6
1 2 3
0 1 3
1 0 1
3 1 0
1 1 1
1 2 1
1 3 1
1 1 2
1 2 2
1 3 2

样例输出

Case #1:
0
1
3
0
1
2

题意:

两个人住在城市u,每天要去城市v,但是要经过一些城市和街道,而且每个城市都有危险值,要求找一条路的从城市u到城市v而且危险值不超过w的最短路径。

思路:

我们考虑floyd算法的动态规划解释,F(i,j,k)代表从i顶点到j顶点可以经过前k个顶点的最短路。对于本题,我们用F [ k ] [ i ] [ j ] 代表从i城市到j城市可以经过危险值是前k小的城市的最短路径。对于每个F [ k ] [ i ] [ j ] ,我们从:

一:从i城市到j城市,不经过危险值是第j小的城市。

二:从i城市到j城市,经过危险值是第j小的城市。

我们从这两种情况中选择最短路径小的那个填充到数组F [ k ] [ i ] [ j ]中去。

所以状态转移方程:

            F [ k ] [ i ] [ j ]=min(F [ k-1 ] [ i ] [ j ] , F[ k-1 ] [ i ] [ id[ k ] ]+F [ k-1 ] [ id[ k ] ] [ j ] )

代码如下:

#include
#define INT 999999999
using namespace std;
int e[210][210][210];//e[k][i][j]代表从i城市到j城市可以经过危险值前k小的城市的最短路径
int id[210];//id[i]代表危险值第i小的城市的编号
int danger[210];//danger[i]代表编号为i的城市的危险值
int t;
const int INF=0x3f3f3f3f;
bool cmp(int a,int b)//按照危险值从小到大对城市的编号排序
{
    return danger[a]

对于正常的floyd算法,我们仅需要一个二维数组就可以实现求最短路了,但是,此题为什么还要用三维数组呢?

因为对于正常的二维数组的floyd算法,我们算出当前从i顶点到j顶点的最短路后就可以覆盖掉前面的求出的i顶点到j顶点的最短路了,对于正常的二维数组的floyd算法,我们不会保存之前求出的i顶点到j顶点当前最短路的结果。但是这个题不同,对于此题的问法,他是多次询问,而且他给定了中转顶点的一些限制,为了使得时间复杂度不会过高,我们就要用三维数组来保存我们之前算出的i顶点到j顶点当前最短路的结果,以便直接从三维数组中拿取。

你可能感兴趣的:(算法)