Description

小明现在要追讨一笔债务,已知有n座城市,每个城市都有编号,城市与城市之间存在道路相连(每条道路都是双向的),经过任意一条道路需要支付费用。小明一开始位于编号为1的城市,欠债人位于编号为n的城市。小明每次从一个城市到达另一个城市需要耗时1天,而欠债人每天都会挥霍一定的钱,等到第k天后(即第k+1天)他就会离开城n并再也找不到了。小明必须要在他离开前抓到他(最开始为第0天),同时希望自己的行程花费和欠债人挥霍的钱的总和最小,你能帮他计算一下最小总和吗?

Solution

显然是最短路问题,求1到n的最短路,由于多出了个欠债人的影响,考虑分层图最短路,用 代表第 天到达 城市的最短路径,那么剩下的问题就可以用 去解决了,后一天的状态能从当前天转移过来。
WA了很多次,没想到当成n条边输入了0.0

Code

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 5;
const int mod = 1e9 + 7;
int a[N], dist[N][11], n, m, k;
bool vis[N][11];
struct qnode {
    int v, cost, day;
    bool operator < (const qnode &r)const{
      return cost > r.cost;
  }
    qnode(int _v = 0, int _cost = 0, int _day = 0): v(_v), cost(_cost), day(_day){}
};
struct Edge {
    int v, cost;
    Edge(int _v = 0, int _cost = 0): v(_v), cost(_cost){}
};
vector<Edge> G[N];
void Dijkstra(int n, int start) {
    for(int i = 1; i <= n; i++) {
        for(int j = 0; j <= 10; j++) {
            dist[i][j] = 1e9;
            vis[i][j] = false;
        }
    }
    priority_queue<qnode> q;
    dist[start][0] = 0;
    q.push(qnode(start, 0, 0));
    while(!q.empty()) {
        qnode tmp = q.top(); q.pop();
        int u = tmp.v;
        int day = tmp.day;
        if(vis[u][day]) continue;
        vis[u][day] = true;
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].v;
            int cost = G[u][i].cost;
            int j = day + 1;
            if(j > k) continue;
            if(!vis[v][j] && dist[v][j] > dist[u][j - 1] + cost + a[j]) {
                dist[v][j] = dist[u][j - 1] + cost + a[j];
                q.push(qnode(v, dist[v][j], j));
            } 
        }
    }
} 
int main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    cin >> n >> m >> k;
    for(int i = 1; i <= m; i++) {
        int x, y, z; cin >> x >> y >> z; 
        G[x].push_back({y, z}), G[y].push_back({x, z});
    }
    for(int i = 1; i <= k; i++) cin >> a[i];
    Dijkstra(n, 1);
    int ans = 1e9;
    for(int i = 0; i <= k; i++) {
        ans = min(ans, dist[n][i]);
    }
    if(ans != 1e9)
        cout << ans << "\n";
    else cout << -1 << "\n";
    return 0;
}