思路:
一道最短路的题。。。
分层最短路的板子。。。
对于图中的所有节点 u u u,他可以拆成 k + 1 k + 1 k+1个节点 u j u_j uj,而且j ∈ \in ∈[0,k]。
分别表示当使用 j j j 次免费通行权限后到达 u u u 号节点的状态。
对于,样例来说那个图的话(脑补)加工中。
list[i][j]为到达i用了j次免费机会的最小花费。
vis[i][j]为到达i用了j次免费机会的情况是否出现过。
对于某些路径,我们可以选择使用机会,也可以选择不使用机会。
之后就分两种情况 :
void spfa() {
int head = 1;
int tail = 2;
memset(list, 0 ,sizeof(list));
list[1][0] = ks;
list[1][1] = 0;
while(head != tail) {
int x = list[head][0];
int c = list[head][1];
for(int k = last[x];k;k = a[k].next) {
int y = a[k].y;
if(f[x][c] + a[k].dis < f[y][c]) {
f[y][c] = f[x][c] + a[k].dis;
if(vis[y][c] == false) {
vis[y][c] = true;
list[tail][0] = y;
list[tail][1] = c;
tail ++;
if(tail == a_b) {
tail = 1;
}
}
}
if(f[x][c] < f[y][c + 1] && c < d_k) {
f[y][c + 1] = f[x][c];
if(vis[y][c + 1] == false) {
vis[y][c + 1] = true;
list[tail][0] = y;
list[tail][1] = c + 1;
tail ++;
if(tail == a_b){
tail = 1;
}
}
}
}
head ++;
if(head == a_b) {
head = 1;
}
vis[x][c] = false;
}
}