链接:点击打开链接
题意:N个点M条的有向无环图,问从1走到n花费时间不超过T最多能经过多少个城市
代码:
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
struct node{
int to,cost;
};
vector<node> G[5005];
int n,m,T;
int vis[5005];
int dp[5005][5005],nex[5005][5005];
void dfs(int s){ //dp[i][j]表示在第i点经过j个点到n点的最小距离
int i,j,tmp;
if(vis[s]) //每个点只能进过一次,只有这样复杂度才是O(n)
return;
vis[s]=1;
for(i=0;i<G[s].size();i++){
tmp=G[s][i].to;
dfs(tmp);
for(j=2;j<=n;j++){ //从后向前dp,也可以从前向后用拓扑加dp
if(dp[tmp][j-1]+G[s][i].cost<dp[s][j]){
dp[s][j]=dp[tmp][j-1]+G[s][i].cost;
nex[s][j]=tmp;
}
}
}
}
int main(){
int i,j,u,v,w,st,ans;
while(scanf("%d%d%d",&n,&m,&T)!=EOF){
for(i=1;i<=n;i++)
G[i].clear();
for(i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
if(v==1||u==n) //因为是从1点走向n点,所以到1和出n的都没有用
continue;
G[u].push_back((node){v,w});
}
memset(dp,INF,sizeof(dp));
memset(vis,0,sizeof(vis));
vis[n]=1,dp[n][1]=0;
dfs(1);
for(i=n;;i--){
if(dp[1][i]<=T){
ans=i;
break;
}
}
printf("%d\n",ans);
st=1;
printf("%d",st);
while(st!=n){
st=nex[st][ans--];
printf(" %d",st);
}
printf("\n");
}
return 0;
}