给出一个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;
} 
京公网安备 11010502036488号