描述
There are n cities connected by m flights. Each fight starts from city u and arrives at v with a price w.
Now given all the cities and fights, together with starting city src and the destination dst, your task is to find the cheapest price from src to dst with up to k stops. If there is no such route, output -1.
The number of nodes n will be in range [1, 100], with nodes labeled from 0 to n - 1.
The size of flights will be in range [0, n * (n - 1) / 2].
The format of each flight will be (src, dst, price).
The price of each flight will be in the range [1, 10000].
k is in the range of [0, n - 1].
There will not be any duplicated flights or self cycles.
样例
Input:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 1
Output: 200
Input:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 0
Output: 500
思路
见到这道题的第一反应是最短路算法。按照dfs,记录每个节点的深度,建立堆每次选择最短的边搜索,遇到dst就结束算法。(这里可能和Prim有点搞混)。考虑到建立了边的堆集,时间复杂度会有O( E log E)。
后来发现不能直接结束算法,因为可能存在负环,所以必须要搜索所有的点。
正确的思路是dp。 f( i , j )表示到达第i个点用了至多j步的时候的距离。
转移方程是: f( i , j ) = min{ f( pre(i), j-1 )+weight( pre(i), i ), f( i, j-1 ) }
也就是说到达第i个点用了至多 j 步的距离相当于到达 i 的前序节点用了至多 j-1 步,或者(没有多走),用了至多 j-1 步就到了 i 。
完成需要填满 max { O(NK), O(E) }
代码
struct edge
{
int src;
int weight;
edge( int d, int w )
{
this->src = d;
this->weight = w;
}
edge()
{
}
};
int findCheapestPrice(int n, vector<vector<int>> &flights, int src, int dst, int K) {
// write your code here
vector<edge> empty;
vector<vector<edge>> pre(n, empty);
int **f = new int*[n];
int k = K+1;
for(int i=0; i<n; i++)
{
f[i] = new int[k];
}
for(auto i:flights) //记录前件
{
edge tmp1(i[0], i[2]);
pre[i[1]].emplace_back(tmp1);
}
int sizeOfedge = flights.size();
int infty = 1 << 30;
f[src][0] = 0;
for(int i=1; i<n; i++)
{
if( i == src )
{
continue;
}
f[i][0] = infty;
}
for(int j=1; j<=k; j++)
{
for(int i=0; i<n; i++)
{
int min = infty;
for(auto q:pre[i])
{
if( f[q.src][j-1]+ q.weight < min )
{
min = f[q.src][j-1] + q.weight;
}
}
if(min > f[i][j-1])
{
min = f[i][j-1];
}
f[i][j] = min;
}
}
int dstMin = infty;
for(int j=0; j<=k; j++)
{
if( f[dst][j] < dstMin )
{
dstMin = f[dst][j];
}
}
if( dstMin == infty )
{
return -1;
}
else
{
return dstMin;
}
}