给出一个n个点m条边的有向无环图。
问从1到n,在距离不超过k的情况下最多经过多少点,并输出一个方案。
SPFA + dp
dp[i][j]表示第i个点经过j条边的最小值
然后二维标记,直接跑SPFA
#include <bits/stdc++.h> using namespace std; const int inf = 1e9 + 9; const int maxn = 1e5 + 5; int head[maxn][2], tot[2]; const int maxm = 5050; int dp[maxm][maxm]; bool vis[maxm][maxm]; int pre[maxm][maxm]; struct Edge { int u, v, w, next; }edge[maxn][2]; int n, m, k; struct node { int u, c; node(int uu, int cc) { u = uu; c = cc; } }; void init() { memset(head, -1, sizeof(head)); tot[0] = 1; tot[1] = 1; } void add(int u, int v, int w, int i) { edge[tot[i]++][i].u = u; edge[tot[i]][i].v = v; edge[tot[i]][i].w = w; edge[tot[i]][i].next = head[u][i]; head[u][i] = tot[i]; } void spfa(int s) { queue<node> que; que.push(node(1, 0)); vis[1][0] = 1; dp[1][0] = 0; while (!que.empty()) { node t = que.front(); que.pop(); int u = t.u; vis[u][t.c] = 0; for (int i = head[u][0]; i != -1; i = edge[i][0].next) { int to = edge[i][0].v; if (dp[t.u][t.c] + edge[i][0].w <= k && dp[to][t.c + 1] > dp[t.u][t.c] + edge[i][0].w) { dp[to][t.c + 1] = dp[t.u][t.c] + edge[i][0].w; pre[to][t.c + 1] = u; if (!vis[to][t.c + 1]) { que.push(node(to, t.c + 1)); vis[to][t.c + 1] = 1; } } } } } int ans[maxn], t; void dfs(int u, int c) { if (pre[u][c] == 0) { if (u == 1) { cout << u << " "; } return ; } dfs(pre[u][c], c - 1); cout << u << " "; } int main() { int u, v, w; init(); scanf("%d%d%d", &n, &m, &k); for (int i = 0; i <= n; i++) { for (int j = 0; j <= n; j++) { dp[i][j] = inf; } } for (int i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &w); add(u, v, w, 0); add(v, u, w, 1); } spfa(1); int s = 0; for (int i = n-1; i >= 1; i--) { if (dp[n][i] <= k) { s = i; break; } } cout << s + 1 << endl; dfs(n, s); return 0; }