Codeforces 721C Journey - DAGDP
阿新 • • 發佈:2018-11-04
設dp[i][j]表示到第i個點一共經過j個點時的最小路徑長度,按拓撲序轉移就好了
考慮到到達第i個點並且目前走過的點數量固定時,顯然不需要知道以前走的是哪些點,只要保證此時路徑長度最短,就會得到更優的答案
注意到k不會超過int,所以陣列不需要開longlong(開了會爆記憶體。。。)判斷的時候強轉就好了
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; #define debug(x) cerr << #x << "=" << x << endl; typedef long long ll; const int MAXN = 5000 + 10; int n,m,k,ans,edge_tot,tot; int ind[MAXN],last[MAXN],pre[MAXN][MAXN],pla[MAXN]; int dp[MAXN][MAXN]; queue<int> q; struct Edge{ int u, v, w, to; Edge(){} Edge(int u, int v, int w, int to) : u(u), v(v), w(w), to(to) {} }e[MAXN]; inline void add(int u, int v, int w) { e[++edge_tot] = Edge(u, v, w, last[u]); last[u] = edge_tot; } void topo() { for(int i=1; i<=n; i++) if(!ind[i]) q.push(i); while(!q.empty()) { int x = q.front(); q.pop(); for(int i=last[x]; i; i=e[i].to) { int v = e[i].v, w = e[i].w; ind[v]--; if(!ind[v]) q.push(v); for(int j=1; j<=n; j++) { if((ll)dp[x][j-1] + w <= k) { if(dp[v][j] > dp[x][j-1] + w) { dp[v][j] = dp[x][j-1] + w; pre[v][j] = x; } } } } } } int main() { scanf("%d%d%d", &n, &m, &k); for(int i=1; i<=m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); ind[v]++; add(u, v, w); } memset(dp, 0x3f, sizeof(dp)); int temp_inf = dp[1][1]; dp[1][1] = 0; pre[1][1] = 1; topo(); for(int i=1; i<=n; i++) { if(dp[n][i] != temp_inf) ans = i; } printf("%d\n", ans); pla[++tot] = n; for(int i=ans; i>1; i--) { pla[++tot] = pre[pla[tot-1]][i]; } for(int i=tot; i; i--) { printf("%d ", pla[i]); } return 0; }