题目大意
给定一张无向图,每条边有费用,每走 条边会有额外费用
,至多走
条边。问从点
到点
的最小费用路。
题解
把每一个点拆成 个点,相当于对点记录一下时间即可直接套用 Dijkstra 算法。
#include <bits/stdc++.h>
#define REP(temp, init_val, end_val) for (int temp = init_val; temp <= end_val; ++temp)
#define REPR(temp, init_val, end_val) for (int temp = init_val; temp >= end_val; --temp)
#define fst first
#define snd second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> intpair;
int read(){
int f = 1, x = 0;
char c = getchar();
while (c < '0' || c > '9'){if(c == '-') f = -f; c = getchar();}
while (c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
return f * x;
}
int n, m, k;
priority_queue<pair<int, intpair > > pq;
int dis[1005][12];
int to[20005], nxt[20005], w[20005], at[1005] = {0}, cnt = 0;
int c[12];
void init(){
n = read(), m = read(), k = read();
REP(i, 1, m){
int u = read(), v = read(), ww = read();
to[++cnt] = v, nxt[cnt] = at[u], w[cnt] = ww, at[u] = cnt;
to[++cnt] = u, nxt[cnt] = at[v], w[cnt] = ww, at[v] = cnt;
}
REP(i, 1, k){
c[i] = read();
}
}
void solve(){
memset(dis, 0x3f, sizeof(dis));
dis[1][0] = 0;
pq.push(make_pair(0, make_pair(1, 0)));
for (; ; ){
while (!pq.empty()){
if (-pq.top().fst > dis[pq.top().snd.fst][pq.top().snd.snd])
pq.pop();
else break;
}
if (pq.empty()) break;
int d = -pq.top().fst;
int p = pq.top().snd.fst;
int tm = pq.top().snd.snd;
pq.pop();
if (tm == k) continue;
for (int i = at[p]; i; i = nxt[i]){
if (d + w[i] + c[tm + 1] < dis[to[i]][tm + 1])
dis[to[i]][tm + 1] = d + w[i] + c[tm + 1],
pq.push(make_pair(-dis[to[i]][tm + 1], make_pair(to[i], tm + 1)));
}
}
int ans = 0x3f3f3f3f;
REP(i, 0, k) ans = min(ans, dis[n][i]);
printf("%d\n", ans == 0x3f3f3f3f ? -1: ans);
}
int main(){
init();
solve();
return 0;
} 
京公网安备 11010502036488号