Journey

时间:2023-11-21 21:57:20

Journey

题目链接:http://codeforces.com/problemset/problem/721/C

dp/记忆化搜索/拓扑排序

刚开始想到用bfs+dp,fst(然而中间有一步逻辑错了,不得不说pretest真心弱,然后rank一掉回到*),改正后MLE了,状态没去重存不下...

看了下其他人的,基本用的是记忆化搜索,复杂度是O(m*n);看了下队友ac的,以为是bfs,问了下回答说是拓扑排序(不会=、=)

游少给了一种直接dp的思路Orz,复杂度是O(m*n):

其中time[i][j]表示经过i个结点到达j结点所需要的时间,

pre[i][j]表示经过i个结点到达j结点前的结点序号。

代码如下:

 #include<cstdio>
#include<stack>
#define N 5005
using namespace std;
struct node{
int u,v,t;
}egde[N];
int time[N][N],pre[N][N];
int n,m,T;
int main(void){
scanf("%d%d%d",&n,&m,&T);
for(int i=;i<=m;++i)
scanf("%d%d%d",&egde[i].u,&egde[i].v,&egde[i].t);
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
time[i][j]=T+;
time[][]=;
for(int i=;i<n;++i)
for(int j=;j<=m;++j){
int u=egde[j].u;
int v=egde[j].v;
int t=egde[j].t;
if(time[i][u]+t<time[i+][v]){
time[i+][v]=time[i][u]+t;
pre[i+][v]=u;
}
}
int floor;
for(int i=n;i>=;--i)
if(time[i][n]<T+){
floor=i;
printf("%d\n",floor);
break;
}
int nod=n;
stack<int>s;
while(pre[floor][nod]){
s.push(pre[floor][nod]);
nod=pre[floor][nod];
floor--;
}
while(!s.empty()){
nod=s.top();
s.pop();
printf("%d ",nod);
}
printf("%d\n",n);
}