【题目链接】
【算法】
dist[i][j]表示到达i号城市,使用了j次魔法,所用时间的最小值
那么,dist[i][j]可以转移到dist[k][j+1]和dist[k][j],一边spfa一边dp,即可
【代码】
#include<bits/stdc++.h>
using namespace std;
#define MAXN 55
#define MAXM 2010
const int INF = 1e9;
int i,n,m,k,a,b,t,ans = INF,tot;
int head[MAXN],inq[MAXN][MAXN],dist[MAXN][MAXN];
struct Edge
{
int to,cost,nxt;
} e[MAXM];
template <typename T> inline void read(T &x)
{
int f = 1; x = 0;
char c = getchar();
for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
x *= f;
}
template <typename T> inline void write(T x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9) write(x/10);
putchar(x%10+'0');
}
template <typename T> inline void writeln(T x)
{
write(x);
puts("");
}
inline void add(int u,int v,int w)
{
tot++;
e[tot] = (Edge){v,w,head[u]};
head[u] = tot;
}
inline void spfa(int s)
{
int i,j;
queue< pair<int,int> > q;
pair<int,int> cur;
for (i = 1; i <= n; i++)
{
for (j = 0; j <= k; j++)
{
dist[i][j] = INF;
}
}
dist[1][0] = 0;
q.push(make_pair(1,0));
inq[1][0] = 1;
while (!q.empty())
{
cur = q.front();
inq[cur.first][cur.second] = false;
q.pop();
for (i = head[cur.first]; i; i = e[i].nxt)
{
if (dist[cur.first][cur.second] + e[i].cost < dist[e[i].to][cur.second])
{
dist[e[i].to][cur.second] = dist[cur.first][cur.second] + e[i].cost;
if (!inq[e[i].to][cur.second])
{
inq[e[i].to][cur.second] = 1;
q.push(make_pair(e[i].to,cur.second));
}
}
if ((cur.second + 1 <= k) && (dist[cur.first][cur.second] + e[i].cost / 2 < dist[e[i].to][cur.second+1]))
{
dist[e[i].to][cur.second+1] = dist[cur.first][cur.second] + e[i].cost / 2;
if (!inq[e[i].to][cur.second+1])
{
inq[e[i].to][cur.second+1] = 1;
q.push(make_pair(e[i].to,cur.second+1));
}
}
}
}
}
int main() {
read(n); read(m); read(k);
for (i = 1; i <= m; i++)
{
read(a); read(b); read(t);
add(a,b,t);
add(b,a,t);
}
spfa(1);
for (i = 0; i <= k; i++) ans = min(ans,dist[n][i]);
writeln(ans);
return 0;
}