首先声明 DP解法并不是我想出来的 而是看到题解才明白分层图可以用DP解决 其实好好想一下 Djikstar 的本质无非也就是 BFS + DP ;
后续等我学会了分层图 我也会用分层图的方法来解决这道题目
OK 闲话少叙 先说一下这个题的解题思路
因为Djkstar 堆优化的版本中 存在一个 distance[j] = t.x+ w[i]
; 而且是在前者大于后者的条件下 这太像一个DP了 所有我们有了一个非正式 DP的状态转移方程 我们设f[j][k]
为 j 点用了k次免费花的最少费用 ;
选第k次花费0的方程为 f[j][k]
= f[t.y][k] + w[i]
;
不选第k次花费为0的方程为 f[j][k] = f[t.y][k - 1]
;
至此我们得到了一个 伪DP方程 (详细表示还得看代码hh)
Code :
/*
Djikstar 的本质就是BFS + DP;
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define PII pair<int,int>
using namespace std;
const int M = 100010;
int f[M][15];
bool st[M];
int n,m,p,s,t;
int e[M],w[M],ne[M],h[M],idx ;
priority_queue<PII,vector<PII>,greater<PII> > q;
void add(int a ,int b ,int c)
{
e[idx] = b, ne[idx] = h[a] , w[idx] = c , h[a] = idx ++;
}
void Djikstar()
{
for(int i = 0 ; i <= p ; i ++) f[s][i] = 0;
for(int k = 0 ; k <= p; k ++)
{
memset(st,0,sizeof st);
q.push({0,s});
while(q.size())
{
PII t = q.top(); q.pop();
if(st[t.y]) continue;
st[t.y] = true;
for(int i = h[t.y] ; i != -1 ; i = ne[i])
{
bool is = false;
int j = e[i];
if(k && f[j][k] > f[t.y][k -1])
{
f[j][k] = f[t.y][k - 1] ;
is = true;
}
if(f[j][k] > f[t.y][k] + w[i]) f[j][k] = f[t.y][k] + w[i] , is = true;
if(is) q.push({f[j][k] , j});
}
}
}
}
int main()
{
memset(h,-1,sizeof h);
memset(f,0x3f,M * 15);
cin >> n >> m >> p >> s >> t;
for(int i = 1 ; i <= m; i ++)
{
int x,y,z;
cin >> x >> y >> z;
add(x,y,z);
add(y,x,z);
}
Djikstar();
cout << f[t][p] << endl;
return 0;
}